UnhandledPromiseRejectionWarning in an Express route handler
An async route handler threw an error that nothing caught — Express 4 doesn't automatically catch rejected promises in async route handlers, so the error escapes silently instead of reaching your error-handling middleware. Wrap async handlers in a try/catch (or a helper like `asyncHandler`) that forwards errors to `next()`.
What causes this error
Express 4's routing was built before async/await was common. If an async route handler throws, Express has no built-in way to catch that rejected promise and route it to your error-handling middleware — it just becomes an unhandled rejection, which Node warns about but doesn't recover from gracefully.
The Fix
// Wrong — a throw inside an async handler isn't caught by Express
app.get('/articles/:id', async (req, res) => {
const article = await getArticle(req.params.id); // if this throws, it's unhandled
res.json(article);
});
// Fix — a small wrapper that forwards errors to next()
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
app.get('/articles/:id', asyncHandler(async (req, res) => {
const article = await getArticle(req.params.id);
res.json(article);
}));If you're on Express 5 (still in gradual adoption as of 2026), this is handled automatically — async errors are caught and forwarded to your error middleware without a wrapper needed.
Common causes / variations
- An async handler with no try/catch, relying on Express to catch it automatically (it doesn't, on Express 4)
- A database call or external API request failing inside a route with no error handling
- Not registering a final error-handling middleware at all, so even caught errors have nowhere to go
Related errors
See also: Cannot set headers after they are sent to the client.
Comments
Loading comments...