← Назад к вопросам
Как реализовать глобальный error-handling middleware в Express?
2.0 Middle🔥 201 комментариев
#Node.js и JavaScript#Фреймворки и библиотеки
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Глобальный Error-Handling Middleware в Express
Error-handling middleware — это критически важный компонент любого production-приложения на Express. Это специальный middleware, который автоматически ловит все ошибки и обрабатывает их централизованно.
Основной принцип
В Express error-handling middleware отличается от обычного middleware наличием 4 параметров: (err, req, res, next). Это говорит Express, что это именно error handler. Важно: error-handling middleware должен быть определён последним, после всех остальных middleware и route handlers.
Базовая реализация
// Простой глобальный error handler
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
const message = err.message || "Internal Server Error";
res.status(statusCode).json({
error: {
message: message,
status: statusCode,
},
});
});
Продвинутая реализация с классами ошибок
// Класс для кастомных ошибок приложения
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
Error.captureStackTrace(this, this.constructor);
}
}
// Error handler middleware
const errorHandler = (err, req, res, next) => {
// Логирование ошибки (в продакшене отправляй в сервис мониторинга)
console.error(err);
// Валидация данных
if (err.name === "ValidationError") {
return res.status(400).json({
error: {
message: "Validation failed",
details: err.details,
},
});
}
// JWT ошибки
if (err.name === "JsonWebTokenError") {
return res.status(401).json({
error: { message: "Invalid token" },
});
}
// Наш кастомный AppError
if (err instanceof AppError) {
return res.status(err.statusCode).json({
error: { message: err.message },
});
}
// Неожиданная ошибка
res.status(500).json({
error: { message: "Internal Server Error" },
});
};
app.use(errorHandler);
Асинхронные операции
Главная сложность — ловля ошибок из асинхронных функций. Для этого используй обёртку:
// Обёртка для ловли ошибок в async route handlers
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// Использование
app.get("/users/:id", asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
if (!user) {
throw new AppError("User not found", 404);
}
res.json(user);
}));
Production-ready решение
const errorHandler = (err, req, res, next) => {
const isDevelopment = process.env.NODE_ENV === "development";
// Логирование + мониторинг (Sentry, DataDog и т.д.)
if (!isDevelopment) {
logger.error({
message: err.message,
stack: err.stack,
path: req.path,
method: req.method,
});
}
const statusCode = err.statusCode || 500;
const message = isDevelopment ? err.message : "Internal Server Error";
res.status(statusCode).json({
error: {
message,
...(isDevelopment && { stack: err.stack }),
},
});
};
Ключевые моменты
- Порядок имеет значение: error handler должен быть последним
app.use() - Все ошибки должны быть пойманы: используй asyncHandler для асинхронного кода
- Никогда не отправляй стек-трейс в продакшене: это уязвимость
- Логирование: обязательно логируй в продакшене для отладки инцидентов
- HTTP статусы: используй правильные коды (400, 401, 403, 404, 500)