JavaScript unhandledrejection Event Guide
This article provides an overview of the
unhandledrejection event in JavaScript, explaining how
JavaScript tracks uncaught asynchronous errors, how the event functions
across browser and Node.js environments, and how developers can
implement global listeners to prevent silent application failures and
improve debugging.
What is the
unhandledrejection Event?
In JavaScript, asynchronous operations are predominantly handled using Promises. A Promise exists in one of three states: pending, fulfilled, or rejected. When an asynchronous operation fails or an error is thrown inside a Promise chain, the Promise enters the rejected state.
If a rejected Promise lacks a rejection handler (such as a
.catch() block or a wrapping try...catch in an
async/await context), it becomes an unhandled
rejection. When this occurs, the JavaScript runtime emits the
unhandledrejection event on the global object to signal
that an asynchronous error was not caught locally.
How JavaScript Monitors Uncaught Async Errors
Traditional error-handling mechanisms like
window.onerror or standard try...catch blocks
are designed to intercept synchronous runtime errors. Because Promise
executions are deferred to the microtask queue, errors occurring inside
asynchronous callbacks bypass synchronous call-stack error handlers.
To track these missed errors, modern JavaScript runtimes monitor the state of all Promises:
- Microtask Queue Evaluation: When a Promise rejects without an attached rejection callback, the runtime flags the Promise internally as unhandled.
- Event Loop Notification: At the end of the
microtask checkpoint, if the Promise remains unhandled, the runtime
dispatches the
unhandledrejectionevent. - Fallback Logging: If no global listener suppresses the default behavior, the runtime outputs an error message directly to the developer console.
Capturing Unhandled Rejections in the Browser
In browser environments, the unhandledrejection event is
dispatched on the global window object. You can listen for
it using window.addEventListener.
window.addEventListener('unhandledrejection', (event) => {
console.warn('Unhandled Promise Rejection Detected:');
console.error('Reason:', event.reason);
console.log('Promise:', event.promise);
// Prevent the default browser console error output
event.preventDefault();
});Event Object Properties
event.reason: The value orErrorobject passed to thereject()call or thrown inside anasyncfunction.event.promise: The specific Promise instance that was rejected.event.preventDefault(): Calling this method prevents the browser from displaying the default uncaught rejection error in the developer console.
Capturing Unhandled Rejections in Node.js
Node.js provides a corresponding mechanism attached to the global
process object via the unhandledRejection
event.
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// Optional: Gracefully terminate the process or log to a monitoring service
});Note: In modern Node.js versions, unhandled Promise rejections cause the process to terminate with a non-zero exit code if not handled.
The rejectionhandled
Event
JavaScript also provides a complementary event called
rejectionhandled. This event fires when a handler (such as
.catch()) is attached to a rejected Promise after
the unhandledrejection event has already fired.
This is useful in debugging environments or custom promise-tracking libraries to reconcile whether a previously flagged unhandled rejection was eventually addressed.
window.addEventListener('rejectionhandled', (event) => {
console.log('Promise rejection was handled late:', event.promise);
});Best Practices for Handling Async Errors
- Centralized Logging: Use the
unhandledrejectionevent to send uncaught error payloads to telemetry or application monitoring platforms (e.g., Sentry, Datadog). - Local Catch Handlers: Rely on
unhandledrejectionas a safety net, not as the primary error-handling flow. Always handle expected failure states at the component or function level usingtry...catchor.catch(). - Standardized Error Objects: Always reject Promises
with standard
Errorinstances (reject(new Error("..."))) rather than strings or plain objects to preserve stack traces.