// Custom error class
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.isOperational = true;
}
}
// Route that throws error
app.get('/error', (req, res, next) => {
next(new AppError('Something went wrong', 500));
});
// Async error wrapper
const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next);
// Usage with async routes
app.get('/users', asyncHandler(async (req, res) => {
const users = await User.find(); // If this throws, error handler catches it
res.json(users);
}));
// Error handling middleware (must be last)
app.use((err, req, res, next) => {
console.error(err.stack);
const statusCode = err.statusCode || 500;
const message = err.isOperational ? err.message : 'Internal Server Error';
res.status(statusCode).json({
success: false,
error: message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
});
});