Stop 05 · Backend with Node.js & ExpressTopics · 7/8

Error Handling

Part of the Full Stack Developer Roadmap

In short

Instead of try/catch with res.status(500) in every route, Express lets you send all errors to one place. One handler, consistent error responses, no leaked stack traces.

Designing how your backend surfaces failures — centralized error middleware and a consistent error response shape your frontend can handle predictably.

The mascot at a first-aid desk puts a bandage on a small dented robot.

Think of it like this

The first-aid desk

At a college fest, anyone who gets hurt is sent to one first-aid desk. Volunteers don't each carry bandages; they just point the way. In Express, every route passes problems to next(err), and one error handler patches them up.

Watch it happen

An error finding its way to the handler

Client
Route
Database
Error handler

GET /orders/99

1/6The client asks for an order.

The big ideas

What you need to know

Four arguments

(err, req, res, next). Express only treats a middleware as an error handler if it has all four.

Register it last

Put the error handler after all routes and other middleware, so it can catch errors from all of them.

Express 5 catches async errors

In Express 5, a rejected Promise in a route goes to the error handler automatically. Express 4 needed manual next(err).

Hide details in production

Log the stack on the server. Send users a short message and maybe a request id.

See it in code

Walk through the code

js
1class HttpError extends Error {2  constructor(status, message) { super(message); this.status = status; }3}4 5app.get("/orders/:id", async (req, res) => {6  const order = await db.orders.findById(req.params.id);7  if (!order) throw new HttpError(404, "Order not found");8  res.json(order);9});10 11// Always last, after every route12app.use((err, req, res, next) => {13  console.error(err);14  const status = err.status ?? 500;15  res.status(status).json({ error: status === 500 ? "Something went wrong" : err.message });16});

1/4A small error class that carries an HTTP status with the message.

This relies on Express 5, which forwards async errors for you. On Express 4, wrap async handlers or call next(err) yourself.

Save yourself the pain

Common mistakes

Oops

Writing the error handler with three arguments, so Express treats it as normal middleware.

Do this instead

Keep all four parameters, even if you don't use next. The count is how Express recognises it.

Oops

Returning err.message for every error, including database internals.

Do this instead

Only expose messages from errors you created on purpose. Everything else gets a generic message.

Your mission

Centralise your errors

~25 min

Quick check

How does Express know a middleware is an error handler?

Go deeper

  1. 1Build a centralized Express error-handling middleware that catches all thrown errors.
  2. 2Design a consistent JSON error shape, e.g. `{ error: { message, code } }`, used across your whole API.
  3. 3Handle errors on the frontend by checking this consistent shape, not guessing at each endpoint's format.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge