Skip to content

Error codes & HTTP mapping

Every error a strategy raises extends ExecutionRejectedError and carries:

  • code: a stable, machine-readable string. Branch on it, not on the message.
  • source: { pipelineName, strategyName } of the strategy that raised it.
  • toJSON(): { name, code, message, retryAfter?, source? }, safe to log or send.

The HTTP status comes from describeResilienceError() / httpStatusFor() in resilience-pipeline/http. The /http, /fastify and /koa middlewares use the same mapping. A resilience error whose code isn’t in the table maps to 503.

Class code Raised when HTTP Guard Extra fields
TimeoutRejectedError TIMEOUT A timeout fired before the callback finished (addTimeout, withTimeout, waitFor). 504 isTimeoutError timeout (ms)
BrokenCircuitError CIRCUIT_OPEN The circuit is open, or half-open with every probe slot taken. 503 isBrokenCircuitError, isRejection retryAfter (ms until a probe is allowed; 0 when half-open), cause (last failure that opened it)
IsolatedCircuitError CIRCUIT_ISOLATED The circuit is held open by CircuitBreakerManualControl.isolate(). Extends BrokenCircuitError. 503 isBrokenCircuitError, isRejection retryAfter is undefined
RateLimiterRejectedError RATE_LIMITED A token bucket, fixed/sliding window or partitioned limiter has no permit within queueTimeout, its wait queue is full, or the key is blocked. 429 isRateLimitError, isRejection retryAfter (ms, when known)
BulkheadRejectedError BULKHEAD_FULL A concurrency limiter (fixed or adaptive) is full, a queued call waited past queueTimeout, or it was dropped by overflow. Extends RateLimiterRejectedError. 503 isRateLimitError, isRejection reason ('full' | 'queue-timeout' | 'dropped'), active, queued
PermitLimitExceededError PERMIT_LIMIT_EXCEEDED A call asked for more permits (permits(ctx)) than the limiter can ever grant, so waiting can’t help. 429 isRateLimitError, isRejection permits, permitLimit
RateLimiterDeniedError RATE_LIMIT_DENIED The call matched the limiter’s deny predicate. 403 isRateLimitError, isRejection none
LockNotAcquiredError LOCK_NOT_ACQUIRED addLock couldn’t get the lease within wait. 409 isRejection, isResilienceError key

Base classes, mostly useful in instanceof checks and custom strategies:

Class code Notes HTTP Guard
ExecutionRejectedError EXECUTION_REJECTED Base of every strategy error. 503 (default) isResilienceError
CallRejectedError REJECTED Base of every rejection: the call never started, so breakers don’t count it and retry doesn’t retry it by default. 503 (default) isRejection
Class code What it is HTTP Guard
LockLostError LOCK_LOST The lock’s lease couldn’t be renewed while the callback ran. The callback’s signal is aborted with it, and the execution fails with it if the callback then fails. It extends plain Error, so describeResilienceError() returns undefined. Fields: key. none none (check code)
NonRetryableError none Throw it from your callback to stop retrying at once. The caller receives the original error (cause), never the wrapper. none isNonRetryableError
UnexpectedError UNEXPECTED Only from pipeline.settle(): wraps anything that isn’t a strategy error or an error you returned with Outcome.fromError(). Fields: cause. none Outcome.match(…, { UNEXPECTED })

instanceof fails when two copies of the package are loaded (ESM and CJS side by side, or nested installs). The guards check a registered symbol and the code instead, so they keep working:

import {
class ResiliencePipelineBuilder<T = any, E = never, C extends string = never>

Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), … Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.

The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().

ResiliencePipelineBuilder
,
const isBrokenCircuitError: (error: unknown) => error is BrokenCircuitError
isBrokenCircuitError
,
const isRateLimitError: (error: unknown) => error is RateLimiterRejectedError
isRateLimitError
,
const isTimeoutError: (error: unknown) => error is TimeoutRejectedError
isTimeoutError
} from 'resilience-pipeline';
import {
function describeResilienceError(error: unknown): ResilienceErrorDescription | undefined

Transport-neutral description of a resilience error, or undefined for any other error. Use it to build an HTTP response, GraphQL extensions: { code, httpStatus, retryAfter }, a gRPC status, or a WebSocket error frame. Works across duplicate copies of this package (uses error codes, not instanceof).

describeResilienceError
} from 'resilience-pipeline/http';
const
const pipeline: ResiliencePipeline<string, WithErrors<BrokenCircuitError, never, TimeoutRejectedError>>
pipeline
= new
new ResiliencePipelineBuilder<string, never, never>(options?: ResiliencePipelineBuilderOptions): ResiliencePipelineBuilder<string, never, never>

Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), … Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.

The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().

ResiliencePipelineBuilder
<string>({
ResiliencePipelineBuilderOptions.name?: string | undefined

Labels telemetry events.

name
: 'payments' }).
ResiliencePipelineBuilder<string, never, never>.addCircuitBreaker(options?: CircuitBreakerOptions<string>): Next<string, never, never, BrokenCircuitError>
addCircuitBreaker
().
ResiliencePipelineBuilder<string, BrokenCircuitError, never>.addTimeout(options: Duration | TimeoutOptions): Next<string, BrokenCircuitError, never, TimeoutRejectedError>

addTimeout(5000), addTimeout('5s') or addTimeout({ timeout: '5s', onTimeout }).

addTimeout
('2s').
ResiliencePipelineBuilder<string, WithErrors<BrokenCircuitError, never, TimeoutRejectedError>, never>.build(): ResiliencePipeline<string, WithErrors<BrokenCircuitError, never, TimeoutRejectedError>>
build
();
try {
await
const pipeline: ResiliencePipeline<string, WithErrors<BrokenCircuitError, never, TimeoutRejectedError>>
pipeline
.
ResiliencePipeline<string, WithErrors<BrokenCircuitError, never, TimeoutRejectedError>>.execute<string>(callback: (context: ResilienceContext) => MaybePromise<string>, options?: ExecuteOptions): Promise<string>

Runs the callback through the pipeline; throws the final error.

execute
(() =>
function chargeCard(): Promise<string>
chargeCard
());
} catch (
var error: unknown
error
) {
if (
function isTimeoutError(error: unknown): error is TimeoutRejectedError
isTimeoutError
(
var error: unknown
error
))
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@see ― source

console
.
Console.warn(message?: any, ...optionalParams: any[]): void (+1 overload)

The console.warn() function is an alias for

error

.

@since ― v0.1.100

warn
(`timed out after ${
var error: TimeoutRejectedError
error
.
TimeoutRejectedError.timeout: number
timeout
} ms`);
else if (
function isBrokenCircuitError(error: unknown): error is BrokenCircuitError
isBrokenCircuitError
(
var error: unknown
error
))
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@see ― source

console
.
Console.warn(message?: any, ...optionalParams: any[]): void (+1 overload)

The console.warn() function is an alias for

error

.

@since ― v0.1.100

warn
(`circuit open, retry in ${
var error: BrokenCircuitError
error
.
BrokenCircuitError.retryAfter: number | undefined

Milliseconds until the circuit allows a probe call.

retryAfter
} ms`);
else if (
function isRateLimitError(error: unknown): error is RateLimiterRejectedError
isRateLimitError
(
var error: unknown
error
))
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@see ― source

console
.
Console.warn(message?: any, ...optionalParams: any[]): void (+1 overload)

The console.warn() function is an alias for

error

.

@since ― v0.1.100

warn
(
var error: RateLimiterRejectedError
error
.
RateLimiterRejectedError.code: "RATE_LIMITED" | "BULKHEAD_FULL" | "PERMIT_LIMIT_EXCEEDED" | "RATE_LIMIT_DENIED"
code
); // RATE_LIMITED, BULKHEAD_FULL, …
const
const info: ResilienceErrorDescription | undefined
info
=
function describeResilienceError(error: unknown): ResilienceErrorDescription | undefined

Transport-neutral description of a resilience error, or undefined for any other error. Use it to build an HTTP response, GraphQL extensions: { code, httpStatus, retryAfter }, a gRPC status, or a WebSocket error frame. Works across duplicate copies of this package (uses error codes, not instanceof).

describeResilienceError
(
var error: unknown
error
);
// { code, httpStatus, retryAfter (seconds), message, source } or undefined for other errors
}

describeResilienceError() converts retryAfter to seconds (rounded up), ready for a Retry-After header, GraphQL extensions or a gRPC status. On the error itself, retryAfter is in milliseconds.

  • 504 for a timeout. The dependency was too slow; it’s a gateway problem, not the client’s fault (408 would blame the client).
  • 429 for a rate limit. The client is over its quota and can come back after Retry-After.
  • 503 for a full bulkhead. It’s our capacity, not the client’s rate. @nestjs/resilience makes the same choice.
  • 503 for an open circuit. A dependency is down; Retry-After tells clients when the next probe is allowed.
  • 409 for a held lock. Someone else is doing the same work right now.
  • 403 for deny. The limiter refused this caller by policy.

Related: Typed errors, Failures and defaults, Express and Hono.