Lesson 16 / 23

Async Error Handling

Errors thrown inside async handlers need explicit forwarding.

The gotcha

In Express 4, a rejected promise inside an async route handler does not automatically reach the error handler — it crashes silently or hangs the request.

Catch and forward

Wrap the body in try/catch and call next(err) — or use a small helper to avoid repeating it.

const asyncHandler = (fn) => (req, res, next) =>
  Promise.resolve(fn(req, res, next)).catch(next);

app.get('/users/:id', asyncHandler(async (req, res) => {
  const user = await db.users.findById(req.params.id);
  if (!user) {
    const err = new Error('User not found');
    err.status = 404;
    throw err;
  }
  res.json(user);
}));

Express 5 fixes this

Express 5 automatically forwards rejected promises from async handlers to next(err) — the wrapper becomes unnecessary once you're on Express 5.