#Что означает ошибка
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. |
| Неверная логика ошибки | Исключения. | Проверьте. |
#Пошаговое решение
- Запустите с --trace-warningsВ терминале проекта повторите запуск программы в своей среде (
node app.js,npm run startили другую штатную команду) и прочитайте самый первый стек ошибки. Если процесс завершился без полезного сообщения, добавьте временное логирование на границе конкретногоawait/асинхронной функции. Для диагностического запуска иногда полезенnode --trace-uncaught app.js, но не выводите в логи пароли и токены.UnhandledPromiseRejectionсообщает о том, что ошибка осталась необработанной; настоящая причина находится вreason/causeи стеке. - Добавьте try/catch вокруг awaitЕсли у вас есть
async-функция сawait, найдите место, где операция может не выполниться (сеть, файл, база). Оберните эту операцию вtry { ... } catch (error) { ... }, внутри запишите безопасные сведения об ошибке и выберите реакцию: повторить после исправления причины, сообщить пользователю или передать ошибку выше черезthrow. Если ошибка должна прервать операцию, не заменяйте её простымconsole.logс продолжением как будто всё получилось. После правки повторите тот же сбой и проверьте корректный выход/ответ. - Оберните асинхронные обработчики ExpressЕсли промис вызывается без
await, назначьте обработчик.catch(error => ...)в месте запуска или возвращайте промис вызывающему коду для обработки. Например,sendEmail().catch(reportError)допустимо лишь при существующей функцииreportError, которая действительно фиксирует сбой; простоsendEmail()может оставить отказ необработанным. ДляPromise.allучтите, что отказ одного элемента отклоняет общий промис; если нужны результаты всех элементов, рассмотритеPromise.allSettled. Проверяйте, что отправка/запись действительно завершилась, прежде чем показывать «готово». - Установите глобальный обработчикВ Express выясните версию в
package.json: в Express 5 асинхронный обработчик маршрута передаёт rejected promise системе обработки ошибок; в Express 4 обычно требуется явныйnext(err)или совместимая обёртка. Создайте единый обработчик ошибок, который не раскрывает пользователю внутренние стеки. Не применяйте одинаковый образец к обработчикам событий, таймерам, фоновым задачам и HTTP-маршрутам: у них разный жизненный цикл. Проверьте, что клиент получает корректный код HTTP при сбое. - Подключите линтерГлобальный
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-функции, имеющей переменную urltry { const response = await fetch(url); if (!response.ok) throw new Error(`HTTP ${response.status}`); // Дальше обработка корректного ответа} catch (error) { console.error("Ошибка запроса:", error); throw error; // Передать вызывающему уровню, который умеет обработать сбой}