Centralized Error Handling and Async Wrappers
10 min read
Centralized Error Handling and Async Wrappers
In Express 4, unhandled Promise rejections inside route handlers do not automatically reach the error-handling middleware — you must catch them manually and pass the error to next. Express 5 fixes this, but many production codebases still run Express 4.
The asyncWrapper Utility
A thin higher-order function called asyncWrapper (sometimes spelled catchAsync) wraps every async route handler so that any rejected Promise is forwarded to next(err) automatically.
js
// src/middleware/asyncWrapper.js
function asyncWrapper(fn) {
return function (req, res, next) {
Promise.resolve(fn(req, res, next)).catch(next);
};
}
module.exports = asyncWrapper;
// Usage in a route file
const asyncWrapper = require("../middleware/asyncWrapper");
router.get("/orders", asyncWrapper(async (req, res) => {
const orders = await db.order.findMany();
res.json(orders); // any throw is forwarded to next(err)
}));A Custom ApiError Class
js
// src/lib/ApiError.js
class ApiError extends Error {
constructor(status, message) {
super(message);
this.status = status;
}
}
module.exports = ApiError;
// Throwing in a route
const ApiError = require("../lib/ApiError");
router.get("/items/:id", asyncWrapper(async (req, res) => {
const item = await db.item.findUnique({ where: { id: Number(req.params.id) } });
if (!item) throw new ApiError(404, "Item not found");
res.json(item);
}));js
// src/middleware/errorHandler.js — register LAST in app.js
const ApiError = require("../lib/ApiError");
function errorHandler(err, req, res, next) {
const status = err instanceof ApiError ? err.status : 500;
const message = err.message || "Internal Server Error";
console.error(`[${status}] ${message}`, err.stack);
res.status(status).json({ error: message });
}
module.exports = errorHandler;Keep ApiError, asyncWrapper, and errorHandler in src/lib/ or src/middleware/. Import them once in each router file — they eliminate almost all repetitive try/catch blocks across your codebase.
Ready to test yourself?
Practice Express— quiz & coding exercises