Question presented to candidate: "Your Node service catches every error at the top level and returns a 500 without crashing, no matter what went wrong. Is that a good practice?"
What a strong answer should cover:
- π Operational errors are expected, anticipated failures in a correctly-written program: a database connection timing out, a file not existing, a client sending invalid input, a downstream API returning a 503. The program's logic is fine; the world outside it did something the code was written to expect.
- π Programmer errors are bugs: calling a method on
undefined, a typo in a variable name, an incorrect assumption about a function's return shape. The program's logic itself is wrong. - The reason this distinction matters practically: an operational error should be caught and handled β return a 4xx/5xx response, retry, log it, and keep the process running. A programmer error means the process is in an unknown state β continuing to run risks corrupting data or serving wrong results silently, and the safer response is to let the process crash (and let a supervisor like a container orchestrator or process manager restart it fresh).
- This maps directly onto
process.on("uncaughtException", ...)andprocess.on("unhandledRejection", ...): the Node docs' own guidance is to use these as a last-resort log-and-exit point for bugs that were never caught, not as a general-purpose safety net to keep the process alive no matter what. - A useful implementation pattern: a custom
OperationalErrorclass (or anisOperationalflag on thrown errors) lets a top-level handler distinguish "this is an anticipated failure, respond and move on" from "this is a bug, this process should not keep serving traffic." - The common anti-pattern this distinction is meant to prevent: wrapping literally everything in try/catch and always returning a generic 500, which masks real bugs as if they were routine failures and can leave the process silently running in a corrupted state indefinitely.
Clarifying questions expected:
- "Does the process have a supervisor (Kubernetes, PM2, systemd) that will restart it if it exits?" β crashing on a programmer error is only a safe strategy if something restarts the process.
- "Is this error path something a client can trigger repeatedly with normal usage, or a one-off bug?" β decides whether it is truly operational or actually a programmer error masquerading as one.
Code / implementation expected: Yes β a custom error class plus the branching logic in a handler is the clearest way to show the distinction in code, not just describe it.