Error Handling in Node.js
Every non-trivial program encounters errors: a network call times out, a file is missing, a database constraint fires, user input is invalid. How you handle those errors determines whether your app crashes and burns, silently corrupts data, or degrades gracefully while staying up. Node's async nature adds extra complexity — a thrown error inside a callback or an unhandled rejected promise can crash the process if you aren't careful. This section covers the full picture: the error types Node recognises, try/catch with async/await, the operational-vs-programmer distinction, custom error classes, centralised handling, and the two process-level traps — uncaught exceptions and unhandled rejections.
The three channels errors travel through
1. Synchronous throw
throw new Error('bad input') → caught by surrounding try/catch
2. Rejected promise / async throw
async function f() { throw new Error() }
await f() → caught by try/catch around the await
f() → UNHANDLED rejection if no .catch()
3. EventEmitter 'error' event
stream.on('error', handler) → unhandled 'error' throws synchronouslyWhat good error handling looks like end-to-end
Request comes in ↓ route handler — try/catch around all async work ↓ on error: call next(err) with a meaningful Error object ↓ Express error middleware (4-arg) catches it ↓ classifies: operational (send HTTP error) vs programmer (log + 500) ↓ sends a safe, structured JSON error response ↓ process stays up
What this section covers
Page | Covers |
|---|---|
The Error object, system errors, HTTP errors | |
async/await error propagation patterns | |
Which errors to handle vs which to crash on | |
Subclassing Error for domain-specific types | |
Express 4-arg error middleware | |
| |
| |
Draining connections before exit |
The cardinal rules
Never swallow an error silently — at minimum log it; ideally propagate it.
Never expose internal details to the client — stack traces, SQL queries, file paths.
Use
next(err)in Express — don't throw inside async handlers without catching first.Classify before responding — operational errors get HTTP status codes; programmer errors get logged and fixed.
Keep the process up for operational errors; consider controlled restart for programmer errors.