Error Handling
Part of the Backend Developer Roadmap
In short
In the browser an uncaught error breaks one tab. On a server it can crash the whole process for every user. Handling errors well is what makes a backend trustworthy.
Designing how your backend surfaces failures — custom error classes, centralized error middleware, and consistent error response shapes for API consumers.

Think of it like this
The wicketkeeper's gloves
When the batter misses, the ball doesn't fly to the boundary. The wicketkeeper catches it and the game goes on. try/catch is your wicketkeeper: when something fails, you catch it, deal with it, and the server keeps running.
Watch it happen
Where an error travels
1/5Your service calls db.findUser(42). The database is down, so the Promise rejects.
The big ideas
What you need to know
try/catch works with await
Wrap awaited calls in try/catch. A rejected Promise becomes a normal thrown error you can catch.
Throw real Error objects
throw new Error("...") keeps a stack trace. Throwing a plain string loses where it came from.
Custom error classes
class NotFoundError extends Error lets you check instanceof and map each type to the right HTTP status.
Keep the cause
new Error("Payment failed", { cause: err }) wraps a low-level error without losing the original.
See it in code
Walk through the code
1class NotFoundError extends Error {2 constructor(what: string) {3 super(`${what} not found`);4 this.name = "NotFoundError";5 }6}7async function getOrder(id: string) {8 try {9 const order = await db.orders.findById(id);10 if (!order) throw new NotFoundError(`Order ${id}`);11 return order;12 } catch (err) {13 if (err instanceof NotFoundError) throw err;14 throw new Error("Could not load order", { cause: err });15 }16}1/4A custom error class with its own name, so callers can recognise it.
Expected problems, like a missing order, get their own error type. Unexpected ones get wrapped with cause so the logs show the real reason.
Save yourself the pain
Common mistakes
Oops
An empty catch {} that silently swallows the error.
Do this instead
At least log it. A silent catch turns a clear crash into a mystery bug that takes days to find.
Oops
Sending err.stack or raw database errors to the client.
Do this instead
Log details on the server. Send users a short message and a status code, never your internals.
Your mission
Build an error ladder
Quick check
Why is throw new Error("Not found") better than throw "Not found"?
Go deeper
- 1Create a custom `AppError` class carrying a status code and message.
- 2Build a centralized Express error-handling middleware that catches all thrown errors.
- 3Design a consistent JSON error response shape used across your entire API.
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.