DevPath · Learn to code ESPTEN

Errors and robust validation

The Express error middleware

Error handling in Express

In Express, an error middleware is distinguished from the rest by having four parameters: (err, req, res, next). Express inspects the arity (number of arguments) of the function to recognize it, so all four must be declared, even if you don't use next.

function handleErrors(err, req, res, next) {
  const status = err.statusCode || 500;
  res.status(status).json({ error: err.message });
}

Passing the error with next(err)

A handler does not catch or respond to the error itself: it delegates by calling next(err). When an argument is passed to next, Express skips all the normal middleware and handlers and goes straight to the error middleware.

function getUser(req, res, next) {
  const user = find(req.params.id);
  if (!user) {
    return next(new Error("User not found")); // delegates
  }
  res.json(user);
}

Why centralize

Centralizing error handling in a single middleware (registered at the end, with app.use(handleErrors)) avoids repeating try/catch and error responses in every handler. Advantages:

Examples

The error middleware responds with the appropriate status

function handleErrors(err, req, res, next) {
  const status = err.statusCode || 500;
  return { status, body: { error: err.message } };
}

console.log(handleErrors({ message: "Broken" }, {}, {}, () => {}));
console.log(handleErrors({ message: "Doesn't exist", statusCode: 404 }, {}, {}, () => {}));
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
Custom error classes →