#Что означает ошибка
fetch failed
TypeError: fetch failed с причиной ECONNREFUSED ::1:3000 в Node.js 18+ возникает при обращении к localhost: Node при разрешении localhost может сначала получить IPv6-адрес ::1, а сервер слушает только IPv4 127.0.0.1. Ошибка выглядит как необработанный reject промиса и роняет процесс.
Это отдельный случай из общей проблемы необработанных отклонений: причина здесь в разрешении имени localhost.
Решение — указать адрес явно или заставить Node предпочитать IPv4.
Используйте 127.0.0.1 вместо localhost и проверьте запущенный сервис.
#Причины и решения
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| IPv6 localhost::1. | Проявляется как «fetch failed» или близкий по смыслу сбой. | Используйте 127.0.0.1. |
| СервисНе запущен. | Проявляется как «fetch failed» или близкий по смыслу сбой. | Запустите. |
| ПортНеверный. | Проявляется как «fetch failed» или близкий по смыслу сбой. | Исправьте. |
| ПроксиБлок. | Проявляется как «fetch failed» или близкий по смыслу сбой. | Проверьте. |
#Пошаговое решение
- Выведите err.causeПовторите запрос в программе и поймайте исходную ошибку в
try/catch, временно выведя в журналerror.messageиerror.causeбез адресов с секретами. Проверьте, действительно ли причинаECONNREFUSEDс адресом::1и нужным портом: это отказ соединения по IPv6, а не обязательно неисправность DNS. Если адрес или код другой (ENOTFOUND,ETIMEDOUT), описанные ниже действия могут не подойти.fetchвозвращает промис: без обработки ошибка может завершить процесс. - Проверьте, на каком адресе слушает серверНа компьютере, где выполняется Node, проверьте, запущен ли целевой сервер и какой адрес он слушает. Linux: откройте терминал, выполните
ss -ltnи найдите фактический порт (например,:3000); Windows PowerShell:Get-NetTCPConnection -State Listen -LocalPort 3000. В выводе127.0.0.1:3000означает только IPv4 loopback,[::1]:3000— IPv6 loopback; отсутствие порта означает, что сервер ещё не запущен или использует другой порт. Не открывайте порт в брандмауэре без сетевой диагностики. - Укажите 127.0.0.1 вместо localhostЕсли сервер слушает
127.0.0.1, а ошибка возникает именно при соединении с::1, в клиентском URL заменитеhttp://localhost:3000наhttp://127.0.0.1:3000для этого локального сценария. Снова выполните запрос: если ответ получен, проблема была в несовпадении IPv4/IPv6. В Docker и удалённых серверах127.0.0.1указывает на сам контейнер/удалённую машину, а не на сервер-хост: там нужны правильное имя службы и сетевой маршрут. - Запустите Node с --dns-result-order=ipv4firstКак альтернативу на поддерживаемых версиях Node можно проверить порядок разрешения имён командой
node --dns-result-order=ipv4first app.js, гдеapp.js— имя вашего приложения. Это диагностическое изменение, а не универсальное решение; оно может затронуть другие подключения. Другой отдельный способ — настроить сервер слушать IPv6 (::1для локального доступа) при поддержке вашего стека. Адрес::иногда допускает и IPv4-подключения, но это зависит от платформы;0.0.0.0самостоятельно не даёт IPv6. Не публикуйте внутренний сервис в интернет ради исправления локального fetch. - Оберните fetch в try/catchДобавьте обработку отказа
fetchчерезtry/catch, чтобы приложение показывало понятное сообщение и записывалоerror.causeв журнал. Проверьте, что запрос запускается после старта сервера (для тестов дождитесь готовности порта, а не фиксированной паузы). Затем повторите запрос отдельно поhttp://127.0.0.1:3000иhttp://[::1]:3000— это проверка двух протоколов, не обязательная последовательность для пользователя. Если оба соединения отклонены, вернитесь к настройке слушателя и фактическому порту.
#Диагностика
Посмотрите причину: console.error(err.cause) покажет ECONNREFUSED и адрес ::1. Проверьте, на каком адресе слушает сервер: Windows — netstat -ano | findstr :3000, Linux/macOS — ss -ltnp | grep 3000. Если там 127.0.0.1:3000 или 0.0.0.0:3000, а клиент идёт на ::1, причина подтверждена. Проверьте, что сервер вообще запущен.
#Решения
Замените localhost на 127.0.0.1 в URL. Либо запустите сервер на обоих стеках: app.listen(3000, "::") или "::" при корректном и проверенном режиме IPv6; один адрес "0.0.0.0" не обеспечивает прослушивание ::1. Либо задайте порядок для Node: node --dns-result-order=ipv4first app.js (Node 17+), в коде — require("dns").setDefaultResultOrder("ipv4first"). Для Vite/Next настройте host: "127.0.0.1" или "::"; для Docker-проброса проверьте 0.0.0.0 внутри контейнера.
#Обработка ошибки
Оберните вызовы в try/catch: try { await fetch("http://127.0.0.1:3000/api") } catch (e) { console.error(e.cause) }. В тестах (Jest, Vitest, Playwright) поднимайте сервер до запросов и ждите готовности порта (wait-on). Проверьте файл hosts: в нём должны быть записи 127.0.0.1 localhost и ::1 localhost. Проверьте брандмауэр и прокси, которые могут подменять локальные запросы (NO_PROXY=localhost,127.0.0.1).
# Диагностика на Linux; замените 3000 реальным портомss -ltn | grep ":3000"# Альтернативный тест запуска Node (не обязательно):# node --dns-result-order=ipv4first app.js