Error handling is one of the most critical aspects of building robust web applications. In Express.js, proper error handling involves creating a systematic approach to catch, process, and respond to different types of errors that can occur during request processing.
The foundation of Express error handling lies in understanding the distinction between operational errors and programming errors. Operational errors are expected issues that occur during normal application flow—like invalid user input, missing resources, or authentication failures. Programming errors are unexpected bugs in your code, such as null reference errors or type mismatches.
Express provides a built-in error handling mechanism through middleware functions that accept four parameters: (err, req, res, next). These error-handling middleware functions are executed when next() is called with an error argument, or when an unhandled error is thrown in route handlers.
A well-designed error handling system should provide consistent error responses, appropriate HTTP status codes, and sufficient logging for debugging. Custom error classes allow you to categorize errors and attach metadata like status codes and error types, making it easier to handle different scenarios appropriately.
The middleware pipeline order is crucial—error handlers must be registered after all routes and other middleware. Additionally, having a centralized error handler ensures that all errors follow the same response format, improving the client-side developer experience and making your API predictable and reliable.
1import { Request, Response, NextFunction } from 'express';
2
3// Custom error class with structured properties
4class APIError extends Error {
5 constructor(
6 public statusCode: number,
7 public errorType: string,
8 message: string
9 ) {
10 super(message);
11 this.name = 'APIError';
12 }
13}
14
15// Centralized error handler middleware
16const globalErrorHandler = (
17 err: Error,
18 req: Request,
19 res: Response,
20 next: NextFunction
21) => {
22 if (err instanceof APIError) {
23 return res.status(err.statusCode).json({
24 error: {
25 type: err.errorType,
26 message: err.message,
27 timestamp: new Date().toISOString()
28 }
29 });
30 }
31
32 // Handle unexpected errors
33 console.error('Unexpected error:', err);
34 res.status(500).json({
35 error: {
36 type: 'INTERNAL_ERROR',
37 message: 'Something went wrong'
38 }
39 });
40};