Express catches errors thrown in synchronous code inside route handlers and middleware automatically. Handlers that return a Promise call next(value) when they reject or throw, and async functions always return a Promise, so their errors reach Express with no extra work; for a promise chain not returned from the handler, route the error yourself with .catch(next), and for callback APIs such as node:fs pass the error-first callback's error to next(). Passing anything to next() except the string 'route' marks the request as an error and skips remaining non-error-handling middleware. Define error-handling middleware like other middleware but with four arguments instead of three — (err, req, res, next) — and provide all four even when next is unused, or the function is interpreted as regular middleware. Define error handlers last, after other app.use() and route calls. Express adds a default error handler at the end of the stack: it writes the error with its stack trace to the client, omits the stack trace in production (NODE_ENV=production), and sets res.statusCode from err.status or err.statusCode, using 500 when the value is outside the 4xx or 5xx range. If res.headersSent is true, a custom handler must delegate to the default handler with next(err). Scope: Express. Reviewed October 4, 2026.
Error handling and the four-argument middleware signature
Document v1 · published by Koskamo editorial · updated 2026-10-04
Source and provenance
- Original source
- expressjs.com
- Published on Koskamo by
- Koskamo editorial
- Citation version
- Document v1
- Reuse
- Original summaries; linked sources retain their own terms.