Global Exception Handling in Node.js with Express

🌐

Global Exception Handling in Node.js with Express

When building a Node.js application with Express, handling errors in a consistent way is crucial. Without proper error handling, your app could expose sensitive details to clients or simply crash. That's where a global exception handler comes in. Let's break down how it works step by step.
Step 1: Creating a Custom Exception Class

Instead of throwing plain Error objects, we can create a custom error class that carries additional metadata — like HTTP status codes.

TypeScript
export class CustomException extends Error { private status: number; constructor(message: string = "Bad Request", status: number = 400) { super(message); Object.setPrototypeOf(this, new.target.prototype); this.status = status; } public getStatus(): number { return this.status; } }

What's happening here?

  • Extending Error → Our CustomException behaves like a normal JavaScript error.
  • Status code field → Stores the HTTP status (e.g., 400, 404, 500).
  • Prototype fixObject.setPrototypeOf(...) ensures proper inheritance so instanceof checks work correctly.
  • Helper methodgetStatus() makes it easy to retrieve the status code.

This way, instead of just throwing an error message, we can throw something like:

TypeScript
throw new CustomException("User not found", 404);
Step 2: The Global Exception Handler Middleware

Express allows us to define a special error-handling middleware. It must have four parameters: (err, req, res, next).

TypeScript
import { CustomException } from "./custom-exception"; import { Request, Response, NextFunction } from "express"; export const globalException = ( err: unknown, req: Request, res: Response, next: NextFunction ) => { if (err instanceof CustomException) { return res.status(err.getStatus()).json({ message: err.message }); } console.error(err); // Logs unexpected errors for debugging return res.status(500).json({ message: "Internal server error" }); };

How it works

  • If the error is an instance of CustomException, it responds with the custom status code and message.
  • Otherwise, it falls back to a 500 Internal Server Error.
  • Every unknown error is logged to the console for debugging.

This ensures your users always get a clean and safe response, while you keep detailed logs internally.

Step 3: Handling Async Errors with catchAsync

One tricky part of Express is async route handlers. If a Promise rejects, Express won't automatically catch it. That's why we wrap async routes in a helper:

TypeScript
import { Request, Response, NextFunction } from "express"; export const catchAsync = ( fn: (req: Request, res: Response, next: NextFunction) => Promise<any> ) => { return (req: Request, res: Response, next: NextFunction) => { fn(req, res, next).catch(next); }; };

Now, instead of writing:

TypeScript
app.get("/users", async (req, res) => { const users = await User.findAll(); // if this throws, Express won't catch it res.json(users); });

We wrap it like this:

TypeScript
app.get("/users", catchAsync(async (req, res) => { const users = await User.findAll(); res.json(users); }));

If an error occurs inside the async function, .catch(next) passes it directly to the global exception handler.

Putting It All Together
  1. Throw CustomException when you want controlled errors.
TypeScript
if (!user) throw new CustomException("User not found", 404);
  1. Wrap routes with catchAsync to capture async errors.
  2. Register the global handler at the end of your Express app:
TypeScript
app.use(globalException);

Why Use This Pattern?

  • Consistency → All errors go through one central place.
  • Security → You don’t accidentally leak stack traces to clients.
  • Flexibility → Different error types can return different status codes/messages.
  • Maintainability → Cleaner controllers without repetitive try/catch blocks.
👉

Ready for Production

With this setup, your Node.js + Express application will have professional-grade error handling that's clean, safe, and easy to maintain.

Code copied to clipboard!

Comments

Popular Posts