Sentry caught my Express error. The request still hung forever
Description and use
In Express 4, async route errors after await become unhandled rejections when Sentry is initialized, causing hanging requests. Fix by wrapping async handlers with .catch(next) or upgrading to Express 5.
Problem
Express 4 async route throws after await, Sentry reports error but request never completes, process stays alive.
Outcome
Express 4 async errors become unhandled rejections when Sentry is initialized, causing hanging requests. Express 5 handles them correctly. Workaround: wrap async handlers with .catch(next) or upgrade.
Workflow
- Define sync and async routes that throw.
- Initialize Sentry if SENTRY env var set.
- Setup Sentry Express error handler.
- Add custom error middleware to log and respond 500.
- Run server on port 3000.
- Send requests to /sync and /async.
- Observe Sentry reports and request behavior.
- Identify that Express 4 does not handle rejected promises automatically.
- Apply workaround: wrap async handler with .catch(next) or upgrade to Express 5.
- Verify request completes with 500 response.
Evidence
Express 4 does not look at the promise your async handler returns. A throw after an await becomes an unhandled rejection, not a next(err) call.
Without an error SDK, Node 20 kills the process. With @sentry/node initialised, the process survives, the error is reported, and the request hangs.
Fix on Express 4: wrap the handler and .catch(next). Or move to Express 5, where rejected promises go to your error handler on their own.
- Record date: 2026-10-16T21:41:07.561Z