Node.js ยท Chapter 22 of 43

Error Handling

Express has a special kind of middleware for handling errors, defined with four parameters: `(err, req, res, next)`. It should be added last, after all other routes.

Proper error handling prevents servers from crashing and gives clients meaningful error responses instead of stack traces.

Throwing and catching errors

Synchronous errors thrown in route handlers are caught automatically by Express; async errors need to be passed to `next(err)` manually (in Express 4).

Custom error middleware

Define error-handling middleware with four parameters; Express recognizes it by that signature and routes errors to it.

Example 1 (javascript)
app.get('/risky', (req, res) => {
  throw new Error('Something broke');
});

app.use((err, req, res, next) => {
  console.error(err.message);
  res.status(500).json({ error: err.message });
});
Output
Something broke
(response: {"error":"Something broke"})

The four-argument middleware catches the thrown error and sends a clean response.

Example 2 (javascript)
app.get('/async-risky', async (req, res, next) => {
  try {
    await Promise.reject(new Error('Async fail'));
  } catch (err) {
    next(err);
  }
});
Output
Async fail (handled by error middleware)

Async errors must be forwarded to next() to reach the error-handling middleware.

Key points

  • Error middleware has 4 parameters: (err, req, res, next).
  • It should be defined after all other routes/middleware.
  • Sync errors are caught automatically; async errors need next(err).
  • Good error handling avoids leaking stack traces to clients.
๐Ÿ’ก Note: In Express 5+, async errors are automatically caught without manual next(err) calls.

๐Ÿ“ Quick Quiz

1. How many parameters does error-handling middleware take?

2. Where should error-handling middleware be placed?

3. How do you forward an async error to Express's error handler?