- Published on
Error handling Technique in NodeJs
- Authors
- Name
- Ganesh Negi

Error handling Technique in NodeJs.
Error handling is crucial for building reliable and maintainable Node.js applications. A robust error-handling strategy ensures stability, prevents crashes, and improves the user experience. This guide covers essential techniques and best practices for handling errors effectively in Node.js.
Key Error Handling Strategies
Middleware for Centralized Error Handling
Using Built-in Error Classes
Third-party Error Handling Libraries
Error Propagation in Synchronous & Asynchronous Code
Graceful Shutdown Techniques
Error Monitoring & Reporting
Circuit Breaker Implementation
Managing Backpressure in Streams
Automatic Retries for Reliability
Effective Logging & Analytics
1. Centralized Error Middleware in Express
Express allows defining a middleware function to handle errors centrally, improving code maintainability.
app.use((err, req, res, next) => {
res.status(err.status || 500).json({ error: err.message });
});
Example: Handling Errors in Routes
app.get('/users/:id', (req, res, next) => {
if (req.params.id === 'admin') {
return next({ status: 403, message: 'Access denied' });
}
res.send('User access granted');
});
2. Utilizing Built-in Error Classes
Node.js provides standard error classes like Error, TypeError, and RangeError. Custom error classes can also be created.
app.get('/users/:id', (req, res, next) => {
if (req.params.id === 'admin') {
return next({ status: 403, message: 'Access denied' });
}
res.send('User access granted');
});
3. Third-party Error Handling Libraries
Libraries such as @hapi/boom provide structured error management.
const boom = require('@hapi/boom');
app.get('/users/:id', (req, res, next) => {
return next(boom.forbidden('Access denied'));
});
4. Proper Error Propagation
Errors should be propagated correctly to prevent unhandled exceptions.
Synchronous Code
function divide(a, b) {
if (b === 0) {
throw new Error('Cannot divide by zero');
}
return a / b;
}
Asynchronous Code
async function fetchData() {
throw new Error('Data fetch failed');
}
fetchData().catch(console.error);
5. Implementing Graceful Shutdown
Ensure clean application exits by handling shutdown signals and closing resources.
process.on('SIGINT', async () => {
console.log('Closing resources...');
process.exit(0);
});
6. Error Monitoring & Reporting
Use monitoring tools like Sentry or Rollbar to track errors in production.
const Sentry = require('@sentry/node');
Sentry.init({ dsn: 'YOUR_DSN_HERE' });
app.use((err, req, res, next) => {
Sentry.captureException(err);
res.status(500).json({ error: 'Something went wrong' });
});
7. Implementing Circuit Breaker Pattern
Circuit breakers prevent cascading failures by temporarily halting requests after repeated failures.
const CircuitBreaker = require('opossum');
const breaker = new CircuitBreaker(fetchData, { timeout: 3000, errorThresholdPercentage: 50 })
8. Managing Backpressure in Streams
Use proper flow control mechanisms to handle large data streams efficiently.
const fs = require('fs');
const readable = fs.createReadStream('file.txt');
const writable = fs.createWriteStream('output.txt');
readable.pipe(writable);
9. Implementing Automatic Retries
Retry failed operations automatically for better resilience.
const retry = require('async-retry');
retry(() => fetchSomeData(), { retries: 3 }).catch(console.error);
10. Structured Logging & Analytics
Use a logging library like Winston for structured error tracking.
const winston = require('winston');
const logger = winston.createLogger({
level: 'error',
transports: [new winston.transports.Console()]
});
Conclusion
A solid error-handling strategy improves the robustness of Node.js applications. By using middleware, error propagation techniques, monitoring tools, and structured logging, developers can create more reliable and maintainable applications.