/errors/dns/getaddrinfo-eai-again
Error: getaddrinfo EAI_AGAIN (temporary DNS failure)
- tool
- DNS
- exit code
- 1
- versions
- Node.js 18+, glibc getaddrinfo
- os
- linux, macos, windows
getaddrinfo EAI_AGAIN host.example.com means the system resolver could not get an answer right now: EAI_AGAIN is getaddrinfo's "temporary failure in name resolution". Unlike ENOTFOUND, which says the name does not exist, EAI_AGAIN says the lookup itself failed (no reply from the DNS server, a timeout, SERVFAIL). Check network and DNS configuration in the environment where the code runs (container, CI job, VPN), and retry transient failures.
How it appears
Node.js prints the message Error: getaddrinfo EAI_AGAIN registry.npmjs.org followed by the stack, and the error object carries code: 'EAI_AGAIN', syscall: 'getaddrinfo' and the hostname that failed. Check err.code in code, not the message text.
The same failure from other programs on Linux: Temporary failure in name resolution (curl, ping, Python's socket.gaierror: [Errno -3]), and npm error code EAI_AGAIN from npm.
Diagnose
Run these in the same place the error happens (inside the container: docker exec -it NAME sh):
getent hosts registry.npmjs.org # uses the same resolver path as getaddrinfo
cat /etc/resolv.conf # which DNS servers are configured
nslookup registry.npmjs.org 1.1.1.1 # does a public resolver answer?
dig +short registry.npmjs.org # if dig is installedIf a public resolver answers but the configured one does not, the configured DNS server is the problem. If nothing answers, the network itself (route, firewall, proxy) is.
Fixes by environment
| Environment | What to check |
|---|---|
| Docker container | docker run --dns 1.1.1.1, or "dns" in /etc/docker/daemon.json; user-defined networks use Docker's embedded DNS at 127.0.0.11 |
| WSL 2 | The generated /etc/resolv.conf and VPN interaction; generateResolvConf in /etc/wsl.conf |
| CI runner | Network egress rules and the runner's DNS; add retries to installs |
| Corporate network | Use the corporate proxy (HTTPS_PROXY, npm proxy settings) instead of direct DNS |
| High-concurrency Node.js app | dns.lookup uses the libuv thread pool (4 threads by default); cache results or set UV_THREADPOOL_SIZE |
Retry transient failures
async function withRetry(fn, attempts = 3) {
for (let i = 1; ; i++) {
try { return await fn(); }
catch (e) {
if (e.code !== "EAI_AGAIN" || i >= attempts) throw e;
await new Promise((r) => setTimeout(r, 200 * 2 ** i));
}
}
}Retrying ENOTFOUND is pointless (the name does not exist); retrying EAI_AGAIN a few times with backoff often succeeds after a network change.