n8n "getaddrinfo EAI_AGAIN" and "getaddrinfo ENOTFOUND": Fix DNS Errors in Docker and the HTTP Request Node
Error: getaddrinfo EAI_AGAIN time-series-db.localhost Error: getaddrinfo ENOTFOUND api.example.com
"Http request generates error - getaddrinfo EAI_AGAIN" has 27,354 views on the n8n forum (Nov 2, 2026) and no accepted answer. So do t/2203 (11,536 views, EAI_AGAIN on every node), t/12309 (12,315 views, ENOTFOUND that comes and goes) and t/3294 (14,438 views, ENOTFOUND on the MySQL node). Both errors mean the same first thing: n8n couldn't turn the hostname into an IP address, so the request never left your server. This page shows how to tell which of seven causes you have and how to fix each one.
How we checked: Node.js's DNS and CLI docs and its error-mapping source, Docker's networking and Compose docs, n8n's docs and its Docker image source at release 2.45.7, and the musl libc notes on its resolver. We did not reproduce each case in a live Docker setup. Where a cause comes only from a forum thread, we say so.
Paid option: if your workflow calls an API for every row of a Google Sheet, the bulk AI runner treats a request that gets no response (a DNS or network error) as retryable, backs off and resumes where it stopped, instead of failing the run. The Pro Kit adds the Google Sheet header CSV, a 10-minute setup guide and an offline test kit (a local OpenAI, Google Sheets and Gmail mock with the 15-scenario runner), so you can watch the retries and resume work before you use a real API key. This guide stays free.
What EAI_AGAIN and ENOTFOUND mean
n8n runs on Node.js. Before the HTTP Request node, a credential test or an AI node can connect, Node looks up the hostname with dns.lookup(). That calls the operating system's getaddrinfo(), so it reads /etc/hosts and /etc/resolv.conf the same way ping does (Node.js: dns.lookup implementation). The message always ends with the exact hostname that failed. Read it first, because it often shows the problem straight away.
EAI_AGAINis getaddrinfo's "temporary failure": the resolver asked a DNS server and got no usable answer (no reply, a timeout or a server failure). The name may be fine, but DNS from where n8n runs isn't working.ENOTFOUNDis the name Node gives the "this name doesn't exist" results (EAI_NONAMEandEAI_NODATA), as you can see in Node's errors.js. Node's docs add thatENOTFOUNDcan also appear when the lookup fails in other ways (Node.js docs). Usually it's a typo, a name that only exists somewhere else, or something that isn't a hostname at all.
Compare ECONNREFUSED: there the name did resolve, but nothing listens on that port. n8n's docs cover that one separately (HTTP Request node common issues).
Which cause do you have?
| What you notice | Most likely cause |
|---|---|
The hostname in the message contains http, a slash, a port or odd characters | Cause 1: a URL or stray character where a hostname belongs |
The host is localhost or ends in .localhost, and it works in your browser | Cause 2: that name means something else inside a container |
| The host is another container's name | Cause 3: the containers aren't on a shared user-defined network |
| Every outside name fails (api.openai.com, googleapis.com), often with EAI_AGAIN | Cause 4: the container's DNS is broken |
| It fails now and then, mostly in big runs | Cause 5: short-lived DNS failures |
| You're on a company network that only allows web traffic through a proxy | Cause 6: proxy settings |
The name resolves, but you get ETIMEDOUT or ENETUNREACH to an IPv6 address | Cause 7: IPv6 first, not DNS |
Step 0: test DNS from inside the n8n container
Your laptop or server resolving the name proves nothing about the container. Run the same lookup n8n uses, from inside it (replace n8n with your container name from docker ps):
docker exec -it n8n node -e "require('dns').lookup('api.openai.com', (e, a) => console.log(e ? e.code : a))"
docker exec -it n8n cat /etc/resolv.conf
If the first command prints the same error code, the problem is the container's network, not your workflow. If it prints an IP address, try the exact hostname from your error. Note for older forum advice: the official n8n image is built on Alpine Linux and removes the package manager (apk del apk-tools in the base Dockerfile), so "run apk add curl in the container" no longer works. The node -e test above always does, and n8n's docs use wget for an HTTP check.
Cause 1: a URL or stray character where a hostname belongs
Database and other credentials (MySQL, Postgres, Redis and so on) want a bare host such as db.example.com or 10.0.0.5. In t/3294 the error read getaddrinfo ENOTFOUND http://…:90/phpmyadmin/: the whole phpMyAdmin URL was in the Host field, and the fix was to enter only the IP address (and the MySQL port, not the phpMyAdmin web port). In the HTTP Request node the URL needs the scheme, so there the opposite mistake, a missing https://, is the one to check.
If the URL comes from an expression (a sheet, a CSV, a webhook), an invisible space or newline at the end is enough to break the lookup. An n8n staff reply in t/12309 suggests exactly this when the error only hits some rows. Clean it in the field: {{ $json.url.trim() }}.
Cause 2: localhost and .localhost names inside a container
This is the case in the 27,000-view thread t/8412: the URL was https://time-series-db.localhost/exec. Names ending in .localhost are special-use names (RFC 6761). On many Linux desktops, systemd's nss-myhostname resolves any name ending in .localhost to 127.0.0.1 and ::1 (nss-myhostname docs), so the name works on the host. The n8n container is Alpine with its own resolver, and that lookup didn't succeed there.
Even when localhost does resolve in the container, it points at the container itself. n8n's docs: "Inside the n8n container, localhost and 127.0.0.1 point at the container itself, not at the host machine." Use one of these instead:
- The service runs in another container: use its container or Compose service name and its container port, for example
http://questdb:9000(see Cause 3). In t/8412 the next attempt hitECONNREFUSED 172.19.0.9:80, port 80, and the staff reply pointed out that QuestDB's REST API listens on 9000 by default. - The service runs on the host, Docker Desktop (Mac or Windows):
http://host.docker.internal:<port>. - The service runs on the host, Linux: add
--add-host=host.docker.internal:host-gatewaytodocker run, orextra_hostsin Compose (n8n documents both). The service on the host must listen on an address the container can reach, not only on127.0.0.1.
Cause 3: container names on the default bridge network
Docker's docs are direct about this: containers on the default bridge network "cannot refer to each other by name". Name lookup between containers only works on a user-defined network (Docker: networking overview). Docker Compose creates one for each project, where every service is "discoverable by its service name", and service-to-service traffic uses the container port, not the published host port (Docker: networking in Compose).
So getaddrinfo ENOTFOUND postgres or EAI_AGAIN my-api usually means n8n and the other container aren't on the same user-defined network. Typical setups that break: n8n started with docker run and the database in a Compose file, or two separate Compose projects. Fixes:
# connect the running n8n container to the other project's network docker network ls docker network connect <project>_default n8n
Or put both in one Compose file, or share an external network:
services:
n8n:
image: n8nio/n8n
networks: [shared]
networks:
shared:
external: true # created once with: docker network create shared
Then use the service name in n8n, for example postgres as the host and 5432 as the port.
Cause 4: the container's DNS is broken
If even api.openai.com fails in the Step 0 test, n8n is fine and the container can't reach a working DNS server. From Docker's docs: containers on the default bridge get a copy of the host's /etc/resolv.conf, and containers on a custom network use Docker's embedded DNS server at 127.0.0.11, which forwards outside lookups to the DNS servers configured on the host (Docker: DNS services). Things to check:
- Set DNS servers for the container with
--dns(ordns:in Compose). Docker notes that--dns=127.0.0.1means the container's own loopback, so a resolver on the host, such as Pi-hole, needs the host's LAN IP. - The host's DNS changed (a VPN connected, a new router, a cloud network change): restart or recreate the container so it picks up the current settings, and run the Step 0 test again.
- A firewall on the host or the VPS provider blocks the container's outgoing DNS (port 53). In t/2203, n8n's founder points out that the A record from n8n's setup guide is about incoming traffic and unrelated, and suggests something blocking outgoing lookups. The same credentials worked from a laptop.
services:
n8n:
image: n8nio/n8n
dns:
- 1.1.1.1
- 9.9.9.9
Pick DNS servers that give the same answers. The n8n image uses Alpine's musl libc, and musl's resolver asks all listed nameservers at once and takes whichever answers first (musl: functional differences from glibc). Mixing an internal DNS server (which knows your private names) with a public one means private names resolve sometimes and fail other times.
Cause 5: short-lived DNS failures in big runs
When EAI_AGAIN hits a few items in a long run and the same URL works on a rerun, the DNS server is dropping or failing some queries. Three things make that more likely:
- Many lookups at once.
dns.lookup()runs as a blockinggetaddrinfo()call on libuv's small thread pool, which Node's docs warn "can have surprising negative performance implications". Sending hundreds of items through the HTTP Request node at once means hundreds of lookups. - Mixed DNS servers on Alpine, as in Cause 4.
- A failing IPv6 (AAAA) answer. The musl notes say glibc returns a result for an unspecified-family lookup even when one family gets a server failure, and musl doesn't. So a DNS server that fails only AAAA queries can fail lookups on Alpine that work on a Debian host.
Fixes in n8n:
- In the HTTP Request node, add Options → Batching (items per batch plus an interval), so fewer requests and lookups run at the same moment.
- Turn on Settings → Retry On Fail. It's capped at 5 tries and 5 seconds between tries (we checked this in the n8n 2.44.4 source). That covers a DNS blip, not an outage, and it re-runs the whole node.
- For long jobs, set Settings → On Error to Continue (using error output), send failed items through a Wait node and retry them, and record which items finished. Then one bad lookup doesn't stop the run, and a rerun doesn't repeat the work.
Cause 6: a company proxy
On networks that only allow outbound web traffic through a proxy, direct DNS lookups for outside names may be blocked or may return nothing useful. n8n supports the HTTP_PROXY, HTTPS_PROXY, ALL_PROXY and NO_PROXY environment variables, and lowercase versions win over uppercase ones when both are set (n8n: deployment environment variables). The HTTP Request node also has a Proxy option that overrides them for that node. Two things to watch:
- The proxy's own hostname still has to resolve in the container, or use its IP.
- Put internal names in
NO_PROXY(for exampleNO_PROXY=localhost,postgres,questdb,.internal.example.com), so requests to your other containers don't go to the proxy, which can't resolve them.
Cause 7: IPv6 first (when the name does resolve)
Since Node.js 17, dns.lookup() returns addresses in the order the resolver gives them (verbatim) instead of IPv4 first (Node.js: --dns-result-order). If a name has an IPv6 address and your container or host has no working IPv6 route, the connection can fail with ETIMEDOUT or ENETUNREACH to an IPv6 address. That isn't EAI_AGAIN, but people often run into it while working on DNS. n8n's docs describe the local version: localhost can resolve to ::1 first, so use 127.0.0.1. To prefer IPv4 for the whole n8n process, set the environment variable below. Node allows --dns-result-order in NODE_OPTIONS.
NODE_OPTIONS=--dns-result-order=ipv4first
This changes the order of results only. It won't fix a lookup that fails outright.
A Compose file with the usual fixes in one place
services:
n8n:
image: n8nio/n8n
ports: ["5678:5678"]
environment:
- NODE_OPTIONS=--dns-result-order=ipv4first # only if you see IPv6 timeouts
dns: # only if container DNS is broken
- 1.1.1.1
- 9.9.9.9
extra_hosts:
- "host.docker.internal:host-gateway" # Linux: reach services on the host
volumes:
- n8n_data:/home/node/.n8n
questdb:
image: questdb/questdb
# n8n reaches it as http://questdb:9000 (service name + container port)
volumes:
n8n_data:
Add only the lines your Step 0 test calls for. Set your other n8n environment variables as usual. After any change, run the Step 0 lookup again before you rerun the workflow.
FAQ
What does getaddrinfo EAI_AGAIN mean in n8n?
n8n (Node.js) asked the operating system to look up the hostname and got a temporary DNS failure: no reply, a timeout or a server error from the DNS server. The request never left your server. On self-hosted n8n it is almost always a Docker networking or DNS issue, not a problem with the API you're calling.
What is the difference between EAI_AGAIN and ENOTFOUND?
EAI_AGAIN means the DNS lookup failed temporarily, so the name may be fine but DNS isn't working from where n8n runs. ENOTFOUND is Node's name for 'this name doesn't exist' results, which usually means a typo, a full URL in a Host field, or a name that only exists on another machine or network.
Why can't n8n in Docker reach localhost or another container?
Inside the n8n container, localhost is the container itself. Use host.docker.internal for services on the host (on Linux, add host.docker.internal:host-gateway), and the container or Compose service name with the container port for other containers. Name lookup between containers only works on a user-defined network, not the default bridge.
How do I fix DNS inside the n8n Docker container?
Test it with docker exec -it n8n node -e "require('dns').lookup('api.openai.com', console.log)". If that fails, set DNS servers with --dns or the dns: key in Compose, check for a firewall that blocks outgoing DNS, and restart the container after the host's DNS or VPN changes. Use DNS servers that give the same answers, because Alpine's resolver queries them all at once.
Does Retry On Fail fix getaddrinfo EAI_AGAIN?
Only for short blips. Retry On Fail allows at most 5 tries with up to 5 seconds between them. For intermittent failures in big runs, also use the HTTP Request node's Batching option, and send failed items through an error output with a Wait and retry. A broken DNS setup needs the network fixed.
Related guides
- n8n OpenAI 429 "The service is receiving too many requests from you" on Google Sheets: the fix
- n8n "The first argument must be of type string or an instance of Buffer ... Received undefined": What It Means and How to Fix It
- n8n Google OAuth2 "invalid_grant": Why Sheets, Drive and Gmail Credentials Expire (Every 7 Days) and How to Fix It