0
0
ExpressDebug / FixBeginner · 4 min read

How to Handle Async Errors in Express: Simple Guide

In Express, async errors must be passed to the error handler by calling next(error) inside async functions or by using a wrapper function that catches errors and forwards them. This ensures Express knows about the error and can respond properly instead of crashing or hanging.
🔍

Why This Happens

Express does not automatically catch errors thrown inside async functions or promises. If you throw an error or reject a promise inside an async route handler without passing it to next(), Express won't handle it, causing the request to hang or crash the server.

javascript
import express from 'express';
const app = express();

app.get('/data', async (req, res) => {
  // This throws an error but Express won't catch it
  const data = await getDataThatFails();
  res.send(data);
});

app.listen(3000);
Output
UnhandledPromiseRejectionWarning: Error: Failed to get data (node:12345) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
🔧

The Fix

Wrap async route handlers in a try-catch block and call next(error) to forward errors to Express's error handler. Alternatively, use a reusable wrapper function that catches errors and passes them to next. This way, Express can handle the error and send a proper response.

javascript
import express from 'express';
const app = express();

// Wrapper to catch async errors
const asyncHandler = fn => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

app.get('/data', asyncHandler(async (req, res) => {
  const data = await getDataThatFails();
  res.send(data);
}));

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send({ error: err.message });
});

app.listen(3000);
Output
{"error":"Failed to get data"}
🛡️

Prevention

Always handle async errors by forwarding them to Express's error middleware using next(error). Use a reusable async wrapper function to avoid repeating try-catch blocks. Enable linting rules that warn about unhandled promises. Keep a global error handler middleware at the end of your middleware stack to catch all errors.

⚠️

Related Errors

Common related errors include unhandled promise rejections causing server crashes, and forgetting to add error middleware which leads to no error response sent. Also, mixing callback and async patterns can cause confusion in error flow.

Key Takeaways

Always forward async errors to Express error middleware using next(error).
Use a reusable async wrapper to catch and pass errors automatically.
Add a global error handler middleware at the end of your middleware stack.
Avoid unhandled promise rejections to prevent server crashes.
Enable linting rules to detect unhandled async errors early.