Keep the default, throw, unless you have a specific reason. It emits unhandledRejection and, if nothing handles that event, raises the rejection as an uncaught exception. Avoid none, which silences all warnings and lets failed operations go unnoticed. The other modes trade a crash for a warning, and each has a place in batch jobs and scripts.
The five modes
The Node.js CLI documentation describes the --unhandled-rejections flag with these modes:
| Mode | Behavior |
|---|---|
| throw | Emit unhandledRejection. If no hook is set, raise it as an uncaught exception. This is the default |
| strict | Raise it as an uncaught exception. If that exception is handled, unhandledRejection is emitted |
| warn | Always trigger a warning, whether or not a hook is set, without the deprecation warning |
| warn-with-error-code | Emit unhandledRejection. If no hook is set, warn and set the exit code to 1 |
| none | Silence all warnings |
The docs also note that a rejection during the static loading phase of an ES module entry point always raises as an uncaught exception, whatever the mode.
Which one fits which service
throw suits most services. A failure that nobody planned for stops the process, an orchestrator restarts it, and the logs show the stack trace. Failing loudly is a security property, because the alternative is continuing in an unknown state.
strict is stricter: the rejection becomes an uncaught exception first, before any unhandledRejection hook runs. Consider it if you want to ensure no custom hook can quietly absorb a failure.
warn and warn-with-error-code keep the process running. They can fit a batch job or a migration tool where one failed item should not abort the run, as long as the exit code reflects the failure. The second mode sets the exit code to 1 when no hook is set, which is why it suits scripts run by CI.
none has few good uses. Removing the signal means a failed audit write, a rejected token check or a dropped queue message produces no output at all.
Hooks and what they should do
The process docs show how to register a hook with process.on('unhandledRejection', ...) for logging. They also warn that uncaughtException is a last resort mechanism and that it is not safe to resume normal operation afterwards. A hook should log, flush, and let the process end. It should not try to carry on as if nothing happened.
process.on('unhandledRejection', (reason) => {
console.error('Unhandled rejection', reason);
process.exitCode = 1;
});
Set the exit code, as in the example, so a script does not report success. Without it, a handler that only logs can exit with 0.
Pair it with prevention
Flags handle what slips through. The lint rule in why a forgotten await matters stops most of it earlier. Together they mean a missing await is caught in review, and an unexpected rejection is loud in production.
Where flags live
Set the flag in your start script or container command, not only on a laptop. Check that the production entry point uses it, since a flag that only exists in a local script protects nothing.
Quick check
What is the default unhandled rejections mode?
throw, according to the Node.js CLI documentation.
Is warn safe for a web server?
It keeps the process running after a failure you did not plan for, so prefer throw and a restart policy for servers.
Sources
Last reviewed: 19 October 2026.