Promise.prototype.catch()

Registers a handler for a promise's rejection and returns a promise for the recovered value.

Signature
promiseInstance.catch(onRejected)
  • Added in JavaScript ES2015

Parameters

ParameterTypeDescription
$onRejectedFunctionA function called asynchronously when the promise rejects. It receives one argument, reason — the value the promise was rejected with. Its return value becomes the fulfillment value of the promise catch() returns.

Return value

PromiseA new Promise, always pending when returned. If onRejected runs, the new promise settles from its return value or its thrown error; if the original promise fulfills, onRejected is skipped and the new promise fulfills with the same value.

Errors

catch() itself does not throw; an error thrown inside onRejected rejects the promise it returns.

catch(fn) is exactly then(undefined, fn) — a convenience with a name that reads like the statement it mirrors. It attaches only to rejections and leaves fulfilled values alone.

The part people get wrong: it recovers

A catch() handler that returns normally turns the rejection back into a fulfillment. The chain continues as if nothing failed, with your handler's return value — or undefined if you only logged. That is often what you want (supply a default), but it is a trap when downstream code assumes success means real data. To keep the failure travelling, throw from inside the handler.

Placement matters

A catch() only sees rejections from links above it. Put it at the end of the chain to cover everything, or mid-chain to recover from one specific step and let later steps fail independently. Note that neither catch() nor then() can see a synchronous throw that happened before the promise existed — for that, use Promise.try().

A rejected promise with no handler anywhere in its chain surfaces as an unhandled rejection, which most environments report loudly.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Supply a default when a lookup or parse fails
  • Log a failure and stop the chain by rethrowing
  • Silence an expected rejection you deliberately ignore
  • Map a low-level error into a domain-specific one before it propagates

Frequently asked questions

What is the difference between .catch() and .then(null, fn)?

Nothing — catch(fn) is defined as then(undefined, fn) and behaves identically. The named method exists purely for readability at the end of a chain.

Why does my code continue after catch() as if it succeeded?

Because catch() recovers: unless the handler throws or returns a rejected promise, the promise it returns is fulfilled. Rethrow the error inside the handler if downstream code should not run.

Does catch() catch synchronous errors?

Only ones thrown inside a Promise executor or a previous then()/catch() handler. A function that throws before returning a promise throws right at the call site — wrap it in Promise.try() to bring that error into the chain.

More examples

Where you put catch() decides what it sees

The first catch() sits above the throw and never fires; the tail catch does. The second chain shows the recovery effect: after the handler logs and returns nothing, the next then() receives undefined, not an error.

Example · javascript
const p = Promise.resolve(1);

await p
  .catch(() => "x")
  .then(() => { throw new Error("late"); })
  .catch((e) => console.log("tail catch:", e.message));

await p
  .then(() => { throw new Error("early"); })
  .catch((e) => console.log("caught:", e.message))
  .then((v) => console.log("catch returns:", v));

Rethrowing to keep the failure alive

One handler, two outcomes. The recognised error is swallowed and replaced with a usable default; the unrecognised one is rethrown, so it stays a rejection and reaches the next catch() untouched.

Example · javascript
const recover = (e) => {
  if (e.message === "ENOENT") return "default config";
  throw e;
};

await Promise.reject(new Error("ENOENT"))
  .catch(recover)
  .then((v) => console.log(v));

await Promise.reject(new Error("EPERM"))
  .catch(recover)
  .catch((e) => console.log("still failed:", e.message));

Discussion

  • Be the first to comment on this lesson.