Skip to content
Latchkey

Node UnhandledPromiseRejection Crashes the Job in CI - Handle the Rejection

On modern Node the default unhandled rejection mode is throw, so a promise that rejects with no catch terminates the process and fails the CI job.

What this error means

A node process prints UnhandledPromiseRejection (or an unhandled rejection stack) and exits non-zero. The rejecting promise was never awaited or caught.

node
node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^
[UnhandledPromiseRejection: This error originated either by throwing
inside of an async function without a catch block, or by rejecting a
promise which was not handled with .catch().

Common causes

A promise without await or catch

An async call is fired and forgotten; when it rejects there is no handler, so the default throw mode kills the process.

A missing await inside an async function

A rejection bubbles out of an un-awaited inner promise instead of being caught by the surrounding try/catch.

How to fix it

Await and wrap in try/catch

  1. Await the promise so its rejection is observable.
  2. Wrap the await in try/catch to handle the failure.
JavaScript
try {
  await doWork();
} catch (err) {
  console.error(err);
  process.exitCode = 1;
}

Add a global handler as a backstop

  1. Register an unhandledRejection listener to log and exit deliberately.
  2. Treat it as a safety net, not a substitute for local handling.
JavaScript
process.on('unhandledRejection', (err) => {
  console.error(err);
  process.exit(1);
});

How to prevent it

  • Enable the no-floating-promises lint rule, await every promise or attach a catch, and keep the default throw rejection mode so unhandled rejections fail loudly in CI.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →