How to Handle Exception in Express.js

Updated: December 28, 2023 By: Guest Contributor Post a comment

Overview

Express.js is a popular web framework for Node.js designed to facilitate the development of web applications and APIs. Exception handling is a critical aspect of building robust Express.js applications. Proper error handling ensures that your application can gracefully handle and respond to unexpected conditions, maintain integrity, and provide informative feedback to the end-users. In this tutorial, we will explore various methods to handle exceptions effectively in Express.js.

Basic Error Handling

In Express.js, errors can be handled using middleware that catches exceptions. Middleware functions in Express have access to the request object (req), the response object (res), the next middleware function in the application’s request-response cycle (next), and in the case of an error handling middleware, the error object (err). Here’s a simple example:

app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

This middleware logs the error stack and sends a generic response with a status code of 500 to the client.

Using Next with Errors

If an error occurs in a middleware or route handler, you can pass it to the next error handling middleware using the next function:

app.get('/route', (req, res, next) => {
    try {
        // simulate an error
        throw new Error('Oops!');
    } catch (err) {
        next(err);
    }
});

app.use((err, req, res, next) => {
    console.error(err.message);
    res.status(500).send('An error occurred!');
});

Asynchronous Error Handling

Handling errors during asynchronous operations requires a slightly different approach. In Express.js, when you use asynchronous middleware or route handlers, you should pass errors to the next function within the catch block of a Promise or by using an error-first callback:

app.get('/async-route', async (req, res, next) => {
    try {
        const results = await someAsyncOperation();
        res.json(results);
    } catch (err) {
        next(err);
    }
});

Custom Error Types

Defining custom error types allows you to handle different kinds of errors with specific logic. Here is how you can implement custom error handling:

class NotFoundError extends Error {
    constructor(message) {
        super(message);
        this.status = 404;
    }
}

app.use((err, req, res, next) => {
    if (err instanceof NotFoundError) {
        return res.status(err.status).send(err.message);
    }

    res.status(500).send('An unexpected error occurred!');
});

Conclusion

In this tutorial, we’ve gone over the basics of exception handling in Express.js, including middleware for error handling, processing errors in asynchronous code, and creating custom error classes for more granular control. Proper error handling is essential for maintaining application stability, providing meaningful feedback to users, and preventing potential security risks. The methods discussed here lay the groundwork for a solid error handling strategy in your Express.js applications. It’s important to continue learning and refining your error handling as you grow as a developer and your applications become more complex.