Custom Error classes and centralized handling
structured error design.
custom Error subclasses carry a statusCode and flag, the central handler inspects instanceof or statusCode to set the HTTP code and JSON shape, defaulting unknown errors to 500.
What's really being asked
Whether you can design a consistent error model and map domain errors to HTTP responses in one place.
The full answer
Custom Error subclasses let an error carry the information needed to respond. A base ApiError extends Error and stores a statusCode and an isOperational flag; subclasses like NotFoundError or ValidationError set sensible defaults (404, 400). Throwing these from anywhere in the app means the call site declares intent without knowing about HTTP. The centralized error middleware then inspects each error: it reads err.statusCode (or uses instanceof checks) to pick the HTTP code and builds a uniform JSON body, for example { error: { message, code } }. Anything that is not a recognized operational error defaults to 500 with a generic message. In production you log the full error server-side but never send stack traces or internal details to the client; in development you may include more for debugging.
The mistakes people make
Returning HTTP 200 with an error payload, leaking stack traces to clients, mapping status codes inside every controller, or not defaulting unknown errors to 500.
What usually comes next
Operational versus programmer errors, why isOperational matters for shutdown decisions, consistent error envelopes, and logging strategy.
A concrete example
class ApiError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; this.isOperational = true; } } class NotFoundError extends ApiError { constructor(m='Not found') { super(m, 404); } } The handler: app.use((err, req, res, next) => { const status = err.statusCode || 500; res.status(status).json({ error: err.isOperational ? err.message : 'Internal Server Error' }); }); A thrown NotFoundError yields a clean 404 JSON, while an unexpected TypeError yields a generic 500.
Interview question
Why attach a statusCode and isOperational flag to custom Error subclasses?
- a.To bypass the need for an error-handling middleware
- b.To let the centralized handler choose the HTTP code and decide whether the error is safe to exposeCorrect
- c.To make the errors throw faster
- d.To automatically retry the failed request
Why? this is the answer
Carrying statusCode lets one central handler map the error to the right HTTP response, and isOperational signals whether it is an expected, client-safe error versus an unexpected bug. It neither speeds throwing nor replaces the middleware.
Just read this? Test yourself on what you have been reading.
Read the original → expressjs.com
- #error-handling
- #express
- #custom-errors
- #http
- #nodejs
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on error-handling — each one lists the topics its interview covers.
See open roles