getaddrinfo ENOTFOUND (Node, Docker, fetch)

DNS lookup failed before any TCP connection started. The name you asked for does not resolve — often a typo, an empty env var, or a Docker service name that only exists on another network.

What ENOTFOUND means

In Node, Error: getaddrinfo ENOTFOUND some.host is a DNS failure from dns.lookup / getaddrinfo(3). No SYN packet was sent yet — there was no IP to talk to. Axios, undici/fetch, Prisma, Sequelize, Redis clients and http.request all surface the same errno.

Error: getaddrinfo ENOTFOUND db
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:…)
# axios: error.code === 'ENOTFOUND'
# fetch: TypeError: fetch failed → cause.code === 'ENOTFOUND'

Checklist (most common first)

  1. Empty or wrong env var — process.env.DB_HOST is undefined, so the client looks up the literal string "undefined" or falls back to an empty host. Log the resolved URL (redact secrets) before connect.
  2. Typo / wrong TLD — api.exmaple.com, missing subdomain, or a trailing space from a copied .env line.
  3. Docker Compose service name — From another container, use the service name (db, redis) on the Compose network. localhost inside a container is that container, not the host or a sibling. From the host machine, use 127.0.0.1 and the published port.
  4. Private DNS / VPN — Internal names like api.prod.internal only resolve on the corporate VPN or in the cluster. Your laptop outside that network gets ENOTFOUND; production does not.
  5. IPv6-only weirdness — Rare, but a name that returns only AAAA while your path is IPv4-only can confuse some stacks. Try the explicit IPv4, or see ECONNREFUSED ::1 when the name does resolve to loopback.

Quick probes

# Does the name resolve at all?
getent hosts db.example.com
# or: dig +short db.example.com
# or: nslookup db.example.com

# Inside the same container/network as the app:
getent hosts db
ping -c1 db   # ICMP may be blocked; DNS success still matters

# Print what Node will look up (no secrets):
node -e "console.log(process.env.DATABASE_URL?.replace(/:[^:@/]+@/, ':***@'))"

ENOTFOUND vs ECONNREFUSED vs ETIMEDOUT vs browser NXDOMAIN

ErrorMeaning
ENOTFOUNDName → no IP (DNS miss / bad host string)
ECONNREFUSEDIP reached; nothing accepted the port
ETIMEDOUTIP path silent / filtered; see ETIMEDOUT
Browser ERR_NAME_NOT_RESOLVEDSame DNS miss in Chrome/Edge; see ERR_NAME_NOT_RESOLVED

Related

DNS_PROBE_FINISHED_NXDOMAIN · TypeError: fetch failed (Node) · ETIMEDOUT / connect ETIMEDOUT · ECONNREFUSED · localhost refused to connect · ERR_NAME_NOT_RESOLVED · TypeError: Failed to fetch · .env files and secrets

Questions

What does getaddrinfo ENOTFOUND mean?

The hostname could not be resolved to an IP address. Fix the name, DNS, or Docker network — not the TCP timeout.

Why ENOTFOUND for localhost?

Usually an empty host string, the literal word undefined from a missing env var, or a typo like localhos. Real localhost should resolve to 127.0.0.1 / ::1.

Why does it work on my laptop but fail in Docker?

Inside Compose, sibling services use service DNS names. localhost points at the container itself. Use the service name and the internal port.

Is ENOTFOUND the same as ETIMEDOUT?

No. ENOTFOUND fails at DNS. ETIMEDOUT means an IP was chosen but the connect/read timed out.

Can a trailing space in .env cause this?

Yes. DB_HOST=db␠ becomes a different label. Quote values and trim when you load them.

How do I debug fast?

Log the hostname you are about to dial (redact passwords), then getent hosts that exact string from the same machine/container as the app.

Published .

Try it

Related guides

Newest guides