Chapter 7 of 10
Centralised error handling prevents duplicate error logic and ensures consistent error responses across your entire API.
// Express identifies error middleware by the 4-argument signature
app.use((err, req, res, next) => {
console.error(err);
// Different responses for different error types
if (err.name === "ValidationError") {
return res.status(400).json({
error: "Validation failed",
details: err.message,
});
}
if (err.name === "UnauthorizedError") {
return res.status(401).json({ error: "Invalid token" });
}
// Default: internal server error
res.status(err.status || 500).json({
error: process.env.NODE_ENV === "production"
? "Something went wrong"
: err.message,
});
});
// Catch-all 404
app.use((req, res) => {
res.status(404).json({ error: `Route not found: ${req.method} ${req.path}` });
});
// Pass errors to the error handler from route handlers
app.get("/courses/:id", async (req, res, next) => {
try {
const course = await getCourse(req.params.id);
if (!course) return res.status(404).json({ error: "Not found" });
res.json(course);
} catch (err) {
next(err); // pass to error handler
}
});