Operational vs Programmer Errors in Node
Operational errors are expected problems like a failed network request; programmer errors are bugs like reading undefined. Handle the first gracefully, crash the second. The footgun is catching programmer errors and continuing, which corrupts process state.
WHY IT EXISTS: Node.js runs as a long-lived process handling many concurrent requests. When an exception surfaces, you must decide whether the problem is external and recoverable or internal and catastrophic. Without this distinction, teams either crash the server for every missing file or try to keep running after a memory corruption bug. The split exists so you can build resilient systems without masking real defects.
THE MENTAL MODEL: Think of operational errors as weather and programmer errors as a broken foundation. You carry an umbrella for rain, but you do not live in a house with a cracked foundation. Operational errors are part of normal operations: a DNS lookup fails, a client disconnects early, or a config file is missing because an ops step was skipped. Programmer errors mean the code itself is wrong: a variable was misspelled, an API was used incorrectly, or state was mutated in an impossible way. The response to weather is adaptation; the response to a broken foundation is repair.
HOW IT WORKS: In practice, operational errors are caught and routed to error-handling middleware in Express or retried with backoff in a job queue. You log them, alert if thresholds breach, and return a sensible HTTP status. Programmer errors are different. In development, you want them to crash loudly with a stack trace. In production, a process manager like PM2 or systemd should restart the process, but the application itself should not try to continue serving requests from the corrupted context. The V8 engine and Node core assume that after an unexpected exception, internal state may be inconsistent.
WHEN TO USE IT: Use this distinction when designing error-handling strategy for any Node.js service. If you are writing a library, document which thrown errors are operational, like a connection timeout, versus programmer errors, like passing a string where an object is required. If you are building an API, map operational errors to status codes and programmer errors to process termination.
WHEN NOT TO USE IT: Do not use this as an excuse to crash the process for every 404 or validation failure. Those are operational. Also, do not use it to justify a global catch-all that logs and continues; swallowing programmer errors violates the mental model and leads to undefined behavior in future requests.
ONE CANONICAL EXAMPLE: An Express route reads a user ID from request.params.id and queries MongoDB. If the database is down, the driver throws a connection timeout; this is operational. Your error middleware catches it and returns a 503 so the client can retry. If you forgot to check that request.params.id exists before passing it to ObjectId, that is a programmer error. Catching it and returning 400 might seem helpful, but the real fix is to validate inputs at the edge. Worse, if a typo causes a ReferenceError inside a closure, catching that and keeping the server alive means subsequent requests may use partially initialized state.
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.