A single unhandled exception in Node.js will crash the entire server process, dropping all active user connections across your application. To build enterprise systems with 99.99% uptime, you must master the distinction between Operational Errors and Programmer Errors and implement robust error architecture.
AppError ClassStandard JavaScript Error objects lack HTTP status codes and operational flags. Create a reusable domain error class:
// errors/AppError.js
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
this.isOperational = true; // Flags this as a known, handled error!
// Capture clean stack trace omitting this constructor
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = AppError;
Configure top-level listeners to catch unexpected errors and restart cleanly:
// server.js - Process-Level Error Handlers
process.on('unhandledRejection', (reason, promise) => {
console.error('[UNHANDLED REJECTION] Reason:', reason);
// Close server gracefully and exit
process.exit(1);
});
process.on('uncaughtException', (err) => {
console.error('[UNCAUGHT EXCEPTION] Fatal bug encountered:', err);
// Node.js process state is now corrupt. Must exit!
process.exit(1);
});
Boost your server-side JavaScript proficiency by studying these closely connected core modules:
Build global Express error-handling middleware.
Listen for system-level process signals.
Log error stack traces without crashing.