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.

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
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
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
Quick check
How does Express know a middleware is an error handler?
Go deeper
- 1Build a centralized Express error-handling middleware that catches all thrown errors.
- 2Design a consistent JSON error shape, e.g. `{ error: { message, code } }`, used across your whole API.
- 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.