SyntaxStudy
Sign Up
Express.js Async Error Handling Patterns
Express.js Beginner 1 min read

Async Error Handling Patterns

In Express 4, an unhandled promise rejection inside a route handler does not call the error middleware — it either silently swallows the error or (in newer Node versions) crashes the process. The safest Express 4 pattern is a `try/catch` block in every async handler that calls `next(err)` in the catch clause. The `asyncHandler` (or `express-async-errors` package) higher-order function eliminates this boilerplate by wrapping the handler in a `.catch(next)`. This is a thin, zero-dependency solution: require the package once at the top of your app file and all subsequent async route handlers are automatically covered. For uncaught exceptions and unhandled rejections that escape the Express pipeline entirely, register process-level handlers with `process.on('uncaughtException')` and `process.on('unhandledRejection')`. These should log the error and exit the process (allowing a process manager like PM2 to restart it) rather than attempting to recover from an unknown state.
Example
// Pattern 1 – manual try/catch (always safe)
app.get('/a', async (req, res, next) => {
    try {
        const data = await fetchData();
        res.json(data);
    } catch (err) {
        next(err); // forward to error handler
    }
});

// Pattern 2 – asyncHandler wrapper (DRY)
const asyncHandler = fn => (req, res, next) =>
    Promise.resolve(fn(req, res, next)).catch(next);

app.get('/b', asyncHandler(async (req, res) => {
    const data = await fetchData(); // any throw is caught
    res.json(data);
}));

// Pattern 3 – express-async-errors package (global patch)
require('express-async-errors'); // patch Express once
app.get('/c', async (req, res) => {
    const data = await fetchData(); // no wrapper needed
    res.json(data);
});

// Process-level safety net
process.on('unhandledRejection', (reason) => {
    console.error('Unhandled Rejection:', reason);
    process.exit(1); // let PM2/Kubernetes restart
});
process.on('uncaughtException', (err) => {
    console.error('Uncaught Exception:', err);
    process.exit(1);
});