Node.js Best Practice Exception Handling
Data Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.
Introduction
Good exception handling in Node.js is less about catching everything everywhere and more about handling errors at the right layer. Synchronous exceptions, rejected promises, framework middleware, and process-level crash handlers each have a different role, and mixing them up usually leads to hidden failures or unstable recovery behavior.
Handle Errors Close to Where They Occur
For synchronous code, try and catch are still the correct tool.
This works for code that throws during the current call stack. It does not automatically handle asynchronous failures that happen later in callbacks or promise chains.
Use async and await with Local try and catch
In modern Node.js code, most application-level error handling happens around await.
This style keeps error handling readable and avoids deeply nested callback logic. It also makes it clear which function owns recovery and which one simply reports failure upward.
Let Framework Middleware Centralize Request Errors
In web servers, request-level errors should usually flow into one central handler rather than being logged and responded to separately in every route.
This keeps route handlers focused on business logic and gives you one place for logging, status mapping, and response format decisions.
Use Custom Error Types for Expected Failures
Not every error is the same. A validation problem, missing record, and database outage should not all be treated identically.
Typed errors make it easier to map failures cleanly at API boundaries without pattern-matching on message strings.
Process-Level Handlers Are for Logging and Shutdown
Node provides unhandledRejection and uncaughtException, but they should be treated as last-resort crash hooks, not as a normal recovery strategy.
The important operational rule is that an uncaught exception means the process may be in an undefined state. In practice, these handlers are good for synchronous cleanup, final logging, and then exiting so a supervisor can restart the service.
Log Enough Context, But Do Not Hide the Failure
A useful error handler should capture:
- the error object or stack
- the request or job context
- identifiers that help you correlate logs
What it should not do is quietly swallow the failure and keep going as if nothing happened. Silent recovery is often more damaging than an explicit crash, because it leaves the system in a bad state without a clear signal.
For background jobs, the equivalent principle is to fail the job clearly, log the context, and let retry logic or orchestration decide what happens next.
Common Pitfalls
The most common mistake is assuming try and catch will automatically handle asynchronous failures that are not awaited correctly. Another is using global process handlers as if they were a safe place to continue normal operation after a crash. Current Node.js guidance is much stricter: uncaughtException is a last-resort cleanup hook, not a resume point. Developers also lose useful observability by logging only error.message and discarding the stack or request context.
Summary
- Handle synchronous exceptions locally with
tryandcatch. - Use
asyncandawaitwith local handling for asynchronous workflows. - Centralize HTTP request errors in framework middleware.
- Use custom error types when different failures need different responses.
- Treat
unhandledRejectionanduncaughtExceptionas crash-level signals for logging, cleanup, and shutdown, not normal recovery.
Related reading
- node.js cannot find module 'mongodb
- Nodejs Child Process on another server using server to server communication
- Node.js Connection failing on connecting to RabbitMQ
- Node.js distributed shared memory solution
- NodeJS Express Async Not Handling More Requests
- node.js never exits after insert to couchbase, opposite of most node questions
- NodeJS gm getting image size synchronously
- node.js How asynchronous are Async loops really?
System design interview problems on this topic
- Design Google Doc: solution and walkthrough
- Design Facebook Messenger: solution and walkthrough
- Design Typeahead Suggestion: solution and walkthrough
- Design an Online Presence Indicator Service: solution and walkthrough
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseNo course covers this one yet
Basis Lab writes one for you from a sentence about what you want to be able to do, then teaches it and checks you understood. Your first course is free.
Build my courseData Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.