UnhandledPromiseRejectionWarning in an Express route handler

Express.js·Sep 12, 2026·intermediate·
Quick answer

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.

Was this fix helpful?

Comments

Loading comments...

Fix: UnhandledPromiseRejectionWarning in Express async routes | BugFixer | BugFixer