ECONNREFUSED в n8n: причины и быстрый разбор ¶
Обновлено: 2026-05-29
Короткий ответ ¶
ECONNREFUSED в n8n означает, что workflow попытался открыть TCP-соединение, но на указанном адресе и порту никто не принял запрос. Это не ошибка JSON, не проблема IF-ноды и не “n8n сломался”: чаще всего указан неверный host, сервис не запущен, порт закрыт, контейнеры находятся в разных Docker-сетях или используется localhost там, где нужен адрес другого сервиса. Начинайте диагностику из того же окружения, где работает n8n: из контейнера, worker или main process.
Быстрая развилка ¶
| Где ошибка | Типичная причина | Первый тест |
|---|---|---|
HTTP Request к localhost |
localhost указывает на контейнер n8n | заменить на имя сервиса или host gateway |
| Postgres | база не запущена или host неверный | nc -vz postgres 5432 |
| Redis | queue mode смотрит не туда | проверить QUEUE_BULL_REDIS_HOST |
| Внешний API | firewall, IP allowlist, сервис лежит | curl -v из контейнера n8n |
| Webhook в локальный сервис | порт не проброшен или сеть другая | docker network и published ports |
| Ошибка только у worker | env main и worker различаются | сравнить переменные окружения |
Почему localhost почти всегда подозрителен ¶
Если n8n запущен в Docker, localhost внутри workflow — это сам контейнер n8n. Он не указывает на ваш VPS, браузер, соседний контейнер, локальный Postgres на хосте или API, запущенный рядом. Поэтому адрес http://localhost:3000/api в HTTP Request node часто работает в браузере администратора, но падает в n8n с ECONNREFUSED.
Правильные варианты зависят от окружения:
| Где находится целевой сервис | Что указывать из n8n |
|---|---|
| другой сервис в том же Docker Compose | имя сервиса: http://api:3000 |
| Postgres в Compose | postgres:5432 |
| Redis в Compose | redis:6379 |
| сервис на хост-машине | host gateway или реальный IP сервера |
| внешний API | публичный домен и порт |
Шаг 1. Проверьте сервис из контейнера n8n ¶
Не проверяйте только с ноутбука. Нужно воспроизвести соединение из той же сети, где работает n8n.
docker compose ps
docker compose logs -n 100 n8n
docker compose exec n8n sh
Внутри контейнера:
wget -S -O- http://api:3000/health
# или если есть curl
curl -v http://api:3000/health
Для TCP-портов:
nc -vz postgres 5432
nc -vz redis 6379
Если из контейнера соединения нет, workflow не виноват. Чините сеть, host, port, firewall или сам сервис.
Шаг 2. Проверьте Docker Compose network ¶
Контейнеры могут быть запущены, но находиться в разных сетях. Тогда имя сервиса не резолвится или порт недоступен.
Пример нормальной схемы:
services:
n8n:
image: n8nio/n8n
depends_on:
- postgres
- redis
networks:
- app
postgres:
image: postgres:16
networks:
- app
redis:
image: redis:7
networks:
- app
networks:
app:
Если API находится в другом compose-проекте, нужно либо подключить общую external network, либо обращаться к нему через публичный/внутренний адрес, доступный из контейнера n8n.
Шаг 3. Разделите ECONNREFUSED, timeout и DNS ¶
Эти ошибки похожи в интерфейсе, но причины разные:
| Ошибка | Что означает | Где искать |
|---|---|---|
ECONNREFUSED |
адрес найден, порт отказал | сервис/порт/firewall |
ENOTFOUND |
DNS-имя не найдено | host, Docker DNS, домен |
| timeout | соединение не установилось вовремя или ответ слишком долгий | сеть, firewall, API, proxy |
ECONNRESET |
соединение оборвано после старта | proxy, TLS, сервер, лимиты |
Если написано ECONNREFUSED 127.0.0.1:5432, не надо чинить пароль Postgres. До проверки пароля соединение даже не дошло.
Шаг 4. Проверьте env для Postgres и Redis ¶
В self-hosted n8n ошибки подключения к Postgres и Redis часто вызваны переменными окружения. Для Postgres проверьте host, порт, database, user, password и SSL. Для queue mode проверьте Redis host/port и то, что main и worker используют одинаковые значения.
Пример:
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=secret
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
QUEUE_BULL_REDIS_PORT=6379
Если worker запущен отдельно, сравните его env с main. Ситуация “UI работает, jobs не выполняются” часто возникает, когда main и worker смотрят на разные Redis/Postgres или один из процессов всё ещё использует старые переменные.
Шаг 5. Проверьте firewall и allowlist ¶
Для внешних API проблема может быть не в n8n, а в ограничениях принимающей стороны. Сервис может принимать запросы только с определённых IP, блокировать датацентровые адреса, требовать VPN или слушать только внутренний интерфейс.
Проверьте:
- доступен ли порт с VPS;
- не блокирует ли исходящие соединения firewall;
- добавлен ли IP сервера n8n в allowlist;
- не нужен ли HTTPS вместо HTTP;
- не закрыт ли порт на стороне API;
- не поменялся ли DNS после переезда.
Шаг 6. Исправьте URL в credentials и нодах ¶
После сетевой проверки откройте конкретную ноду или credentials. Часто ECONNREFUSED остаётся из-за старого значения: localhost, прежний порт, внутренний dev-домен, IP до миграции. Не исправляйте только одну ноду, если этот URL используется в нескольких workflow. Лучше вынести базовый URL в env или credentials.
Пример безопасного подхода:
INTERNAL_API_BASE_URL=http://api:3000
В workflow:
{{$env.INTERNAL_API_BASE_URL}}/orders/{{$json.order_id}}
Так при переезде меняется env, а не десятки нод.
Контрольный тест после исправления ¶
- Выполните
curlилиwgetиз контейнера n8n. - Запустите минимальный workflow с одним HTTP Request.
- Проверьте, что ошибка не повторяется у worker.
- Запустите production workflow на одном тестовом payload.
- Запишите правильный host/port в README проекта.
FAQ ¶
Почему запрос к localhost работает в браузере, но не работает в n8n?
Потому что браузер и контейнер n8n находятся в разных окружениях. Внутри контейнера localhost — это сам контейнер, а не ваш компьютер или соседний сервис.
Что делать, если Postgres отдаёт ECONNREFUSED?
Проверьте, запущен ли контейнер базы, совпадает ли host, открыт ли порт 5432, находятся ли контейнеры в одной сети и не используется ли localhost вместо имени сервиса.
Почему ошибка есть только в queue mode?
Worker может иметь другие env-переменные или другую Docker-сеть. Сравните DB_*, QUEUE_BULL_REDIS_*, EXECUTIONS_MODE и N8N_ENCRYPTION_KEY у main и worker.
Чем ECONNREFUSED отличается от ENOTFOUND?
ENOTFOUND означает, что имя хоста не удалось найти. ECONNREFUSED означает, что адрес найден, но на порту никто не принял соединение.
Можно ли просто увеличить timeout?
Обычно нет. При ECONNREFUSED порт отказал сразу, поэтому увеличение timeout не исправит неверный host, закрытый порт или неработающий сервис.
Ручная диагностика перед исправлением ¶
Перед тем как менять настройки по теме «/errors/econnrefused/», зафиксируйте не только текст ошибки, но и последний успешный запуск. Для n8n это критично: один и тот же симптом может появиться из-за credentials, изменения payload, лимита API, обновления версии или инфраструктурного сбоя.
Рабочий порядок: изолируйте один execution, сохраните входной item без секретов, проверьте branch с ошибкой и только потом меняйте workflow. Главный риск — исправить симптом на одной ноде, но оставить первопричину в credentials, payload, лимитах API или окружении.
| Слой | Что зафиксировать | Зачем |
|---|---|---|
| Вход | входной item по теме «/errors/econnrefused/»: источник события, внешний ID, время получения и нормализованные поля | позволяет повторить проблему без доступа к production-секретам |
| Контроль | error_count_by_node, retry_count, first_failed_execution, last_successful_execution, affected_workflows | показывает деградацию раньше, чем пользователи начинают писать в поддержку |
| Безопасность | исправить симптом на одной ноде, но оставить первопричину в credentials, payload, лимитах API или окружении | снижает риск скрытых дублей, утечки данных и неконтролируемых write-действий |
| Готовность | есть тест на happy path, пустой вход, повтор и сбой внешнего сервиса для «/errors/econnrefused/» | делает статью пригодной для runbook, а не только для чтения |
Пример безопасного входного контракта ¶
{
"execution_id": "exec_...",
"workflow_id": "wf_...",
"node_name": "node_with_symptom",
"error_message": "точный текст ошибки без токенов",
"input_item_id": "external_or_dedupe_id",
"last_successful_run": "timestamp",
"changed_before_error": ["credentials", "payload", "version", "env"]
}
Критерий готовности ¶
- точный текст ошибки сохранён без токенов и персональных данных
- понятно, какая нода упала первой, а какие ошибки были следствием
- есть минимальный воспроизводимый workflow или тестовый execution
- после исправления проверены retry, error branch и последний успешный сценарий