Express · Lesson 6 of 15
Async Errors and Central Handlers
Wrap async routes, throw http-errors and keep a single error middleware.
- Intermediate
- 14 min read
- 3 objectives
Before this lessonLesson 5: Validation with Zod
What you will learn
- Forward async errors
- Throw an HttpError
- Hide 500 details
Your Progress
0 of 15 lessons 0%
- Lessons0 / 15
- Completed0
- Est. time left~ 4 hours
Create a free account to keep your progress on every device.
In Express 4, a rejected promise inside an async handler never reaches your error middleware unless you forward it. One wrapper plus one handler keeps that consistent.
Wrap async routes
const wrap = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
app.get("/tasks/:id", wrap(async (req, res) => {
const task = await db.task.find(req.params.id);
if (!task) {
const err = new Error("Task not found");
err.status = 404;
throw err;
}
res.json(task);
}));Express 5 does this for you. Until you are on 5, the wrapper (or express-async-errors) is required.
The error middleware
app.use((err, req, res, next) => {
const status = err.status || 500;
if (status >= 500) console.error({ err, requestId: req.requestId });
res.status(status).json({
error: status >= 500 ? "Internal Server Error" : err.message,
});
});http-errors
import createError from "http-errors";
throw createError(409, "Email already registered");