Node.js WindowsLinux

Node.js: UnhandledPromiseRejection — необработанное отклонение промиса

  • Обновлено
  • Чтение ≈ 4 минуты

Краткий ответ

Начиная с новых версий Node, необработанное отклонение промиса завершает процесс. Ниже — причины и порядок действий от простого к сложному.

В этой статье
  1. Что означает ошибка
  2. Причины и решения
  3. Пошаговое решение
  4. Поиск источника
  5. Правильная обработка
  6. Типичные причины самих ошибок

#Что означает ошибка

Сообщение
UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block

UnhandledPromiseRejection / unhandledRejection в Node.js возникает, когда промис отклонён (reject), а обработчика .catch() или try/catch вокруг await нет. С Node 15+ необработанное отклонение завершает процесс с кодом 1.

Нужно найти асинхронный вызов без обработки ошибки.

Трассировка стека указывает место, где создан промис.

Начиная с новых версий Node, необработанное отклонение промиса завершает процесс. Нужно обрабатывать ошибки в async-функциях через try/catch или .catch().

#Причины и решения

Возможная причинаКак узнатьЧто делать
Нет catch у промисаОшибка не поймана.Добавьте.
Забыт awaitПромис не ожидается.Добавьте await.
Ошибка внутри обработчикаСобытия.Оберните try/catch.
Неверная логика ошибкиИсключения.Проверьте.

#Пошаговое решение

  1. Запустите с --trace-warningsВ терминале проекта повторите запуск программы в своей среде (node app.js, npm run start или другую штатную команду) и прочитайте самый первый стек ошибки. Если процесс завершился без полезного сообщения, добавьте временное логирование на границе конкретного await/асинхронной функции. Для диагностического запуска иногда полезен node --trace-uncaught app.js, но не выводите в логи пароли и токены. UnhandledPromiseRejection сообщает о том, что ошибка осталась необработанной; настоящая причина находится в reason/cause и стеке.
  2. Добавьте try/catch вокруг awaitЕсли у вас есть async-функция с await, найдите место, где операция может не выполниться (сеть, файл, база). Оберните эту операцию в try { ... } catch (error) { ... }, внутри запишите безопасные сведения об ошибке и выберите реакцию: повторить после исправления причины, сообщить пользователю или передать ошибку выше через throw. Если ошибка должна прервать операцию, не заменяйте её простым console.log с продолжением как будто всё получилось. После правки повторите тот же сбой и проверьте корректный выход/ответ.
  3. Оберните асинхронные обработчики ExpressЕсли промис вызывается без await, назначьте обработчик .catch(error => ...) в месте запуска или возвращайте промис вызывающему коду для обработки. Например, sendEmail().catch(reportError) допустимо лишь при существующей функции reportError, которая действительно фиксирует сбой; просто sendEmail() может оставить отказ необработанным. Для Promise.all учтите, что отказ одного элемента отклоняет общий промис; если нужны результаты всех элементов, рассмотрите Promise.allSettled. Проверяйте, что отправка/запись действительно завершилась, прежде чем показывать «готово».
  4. Установите глобальный обработчикВ Express выясните версию в package.json: в Express 5 асинхронный обработчик маршрута передаёт rejected promise системе обработки ошибок; в Express 4 обычно требуется явный next(err) или совместимая обёртка. Создайте единый обработчик ошибок, который не раскрывает пользователю внутренние стеки. Не применяйте одинаковый образец к обработчикам событий, таймерам, фоновым задачам и HTTP-маршрутам: у них разный жизненный цикл. Проверьте, что клиент получает корректный код HTTP при сбое.
  5. Подключите линтерГлобальный process.on("unhandledRejection", ...) может помочь зафиксировать причину, но не является способом «исправить» отказ и меняет поведение процесса. Для рабочего сервиса решите политику аварийного завершения и перезапуска с администратором; не считайте продолжение после неизвестного состояния безопасным. После исправления конкретного сбоя повторите действие, убедитесь в обработке ошибки и проверьте журнал на новые необработанные отклонения.

#Поиск источника

Запустите с флагом трассировки: node --trace-warnings app.js, и найдите вызов в стеке. Типичные места: fetch/axios без .catch, async-функция вызывается без await и без обработки, обработчики событий и setTimeout, колбэки Express. Добавьте глобальный обработчик только для логирования: process.on("unhandledRejection", (reason) => { console.error(reason); });.

#Правильная обработка

Оборачивайте await в try/catch: try { const r = await fetch(url); } catch (e) { console.error(e); }. Для цепочек — .catch() в конце. В Express 4 асинхронные обработчики оборачивайте функцией, передающей ошибку в next(err); в Express 5 это встроено. Не забывайте return перед промисами в then. Для параллельных задач используйте Promise.allSettled, если часть может завершиться ошибкой.

#Типичные причины самих ошибок

Сетевые ошибки (ECONNREFUSED, ENOTFOUND, ETIMEDOUT), обращение к undefined в async-функции, ошибки парсинга JSON, отсутствие файла при fs.promises.readFile. Устраните причину, а не только подавите вывод. Включите линтер с правилами no-floating-promises (typescript-eslint) и require-await. Для продакшена используйте менеджер процессов (pm2, systemd), чтобы процесс перезапускался, но ошибки логируйте.

ТекстКоманда
Это фрагмент для async-контекста, не готовый самостоятельный файл. Глобальный unhandledRejection не подменяет обработку в месте вызова.
// Пример внутри async-функции, имеющей переменную url
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
// Дальше обработка корректного ответа
} catch (error) {
console.error("Ошибка запроса:", error);
throw error; // Передать вызывающему уровню, который умеет обработать сбой
}

Так эту ошибку тоже называют

Источники и обновления

Последнее обновление статьи: 1 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.