← Debugging Guides

阅读中文版本

Express — error handler never runs for thrown async errors

Fix Express error handling for async routes by forwarding errors to next or using an async wrapper.

intermediatedebuggingnodeexpress

Symptoms

  • A rejected promise in a route does not trigger the error middleware
  • The request hangs and no response is sent
  • An Express 4 app ignores async thrown errors
  • The process logs an unhandled rejection instead of using the error handler

Possible causes

  • Express 4 does not catch promise rejections from async handlers automatically
  • The handler throws inside an async function without try/catch or next
  • The error middleware is registered before the routes
  • An error is swallowed in a catch that does not rethrow or call next

Diagnosis steps

Check where the error middleware is registered

grep -n "app.use" server.js

Interpretation

Error middleware must be registered after the routes and take four arguments to be recognized as an error handler.

Confirm the async handler shape

grep -n "async (" routes/

Interpretation

Async handlers that throw without forwarding leave the promise rejected and the middleware unaware.

Forward explicitly to next

try { await work() } catch (e) { next(e) }

Interpretation

Calling next with the error routes it to the error middleware instead of leaving an unhandled rejection.

Root cause

Express 4 does not observe promise rejections from async handlers, so a thrown error never reaches the error middleware and the request is left unresolved.

Fix

Wrap async handlers so rejections call next, add a four-argument error middleware after the routes, and avoid swallowing errors without rethrowing or forwarding.

Verify the fix

Trigger the failing route and confirm the error middleware responds with the expected status, and confirm no unhandled rejection is logged.

Symptom walkthrough

An async route handler throws or rejects, yet the express error middleware never runs: the request hangs and the process logs an unhandled rejection instead. Express 4 does not await handler promises, so a rejection escapes the middleware chain. The error handler may also be misordered or lack the four-argument signature that marks it as an error handler.

Fix in practice

Forward every async error to next by wrapping handlers or catching and calling next(error). Register the error middleware after the routes with four parameters so Express recognizes it. Do not swallow errors in a catch that neither rethrows nor calls next.

Verification

Trigger the failing route and confirm the error middleware returns the expected status, then confirm no unhandled rejection appears in the logs. The middleware responding proves errors are being routed correctly.

Diagnostic commands

Check the behavior with commands like these:

grep -n "app.use" server.js
grep -n "async (" routes/
try { await work() } catch (e) { next(e) }