Unhandled promise rejection
An unhandled promise rejection is an asynchronous operation in JavaScript that failed, represented by a promise settling as rejected, with no code attached to handle the failure. The runtime reports it to the console after the fact, often with a less useful stack trace than a thrown error, and the work that was waiting on the promise never completes.
The longer version
A promise represents a result that arrives later: a network response, a file read, a timer. If the operation fails, the promise rejects with a reason. Code handles that by attaching a catch handler or by awaiting inside a try block. When neither exists, the rejection has nowhere to go. The browser waits until the end of the current task, checks whether a handler was attached in time, and if not fires an unhandledrejection event and, unless a listener suppressed it, logs the reason to the console. Whatever was meant to happen after the operation, rendering the data or enabling the button, does not happen.
The synchronous relative is the uncaught exception, which unwinds the call stack at the moment it is thrown. A rejection is reported later, from the event loop, and its stack trace typically shows where the promise was created rather than the user action that triggered it, which makes the console entry harder to connect to what the tester saw, and a promise rejected with a plain string carries no stack at all. The confusion runs the other way too: an exception thrown inside an async function does not become an uncaught exception, it becomes a rejection of that function's promise, so a developer looking for a thrown error finds a rejection instead.
The symptom is a screen that stops updating. A fetch fails because the session expired, the rejection is unhandled, and the loading spinner spins forever with no message. Or a form appears to save, because the click handler returned before the request rejected, and the data is gone. The console holds the reason, but the report says only that the page hung. On the server side, unhandled rejections in a Node process can terminate it, which turns a missing catch into an outage rather than a stuck spinner.
Common questions
What causes an unhandled promise rejection?
An asynchronous operation fails, its promise rejects, and no catch handler or surrounding try block was attached to that promise before the current task ended. Common triggers are a failed network request, a thrown error inside an async function, and a promise chain where the catch was attached to the wrong link.
How is an unhandled promise rejection different from an uncaught exception?
An uncaught exception is synchronous: it is thrown and unwinds the call stack at once. An unhandled promise rejection is asynchronous: the failure settles a promise and is reported later from the event loop, through a separate browser event and often with a less useful stack trace. A throw inside an async function produces a rejection, not an exception.
What does an unhandled promise rejection look like to a user?
Usually a page that stops progressing without saying why: a spinner that never finishes, a list that never loads, a save that seemed to work and did not. Nothing crashes visibly because the failure happened after the user's action returned. The console holds the reason, which is why the report needs it.
How do you fix an unhandled promise rejection?
Attach a handler where the outcome is decided: a catch on the promise chain, or an await inside a try block, and in that handler do something a user can see, such as a message, a retry or a fallback. Adding a global listener only stops the console entry; the spinner still spins forever, because the work that was waiting on the promise never ran.
Can an unhandled promise rejection crash a server?
A Node.js process treats an unhandled rejection as fatal by default and exits, so a missing catch in server code turns a single failed request into an outage until the process manager restarts it. A browser tab never exits for the same reason; the page just stops progressing. The same code path is therefore far more dangerous on the server side.
Bug reports that arrive ready to triage.
Collect replay, console, network and browser context with the Free plan.