Home / Tutorials / DNS

DNS · Network · Degraded

Fix: getaddrinfo ENOTFOUND

Error Error: getaddrinfo ENOTFOUND <hostname>

By the Erzon engineering team · A step-by-step fix, not a forum thread

Error: getaddrinfo ENOTFOUND is the Node.js (and libuv) way of saying the hostname could not be turned into an IP address. The lookup ran, and it came back with nothing. No connection was ever attempted, so firewalls, ports, and the remote service are all irrelevant at this point. The entire problem space is: what name did the process actually ask for, and why did the resolver it used have no answer. That framing turns a vague network error into a short, ordered checklist.

What this error means

The error surfaces in stack traces like this:

Error: getaddrinfo ENOTFOUND api.internal.example.com
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:107:26) {
  errno: -3008,
  code: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: 'api.internal.example.com'
}

getaddrinfo is the standard C library function for name resolution. By default Node calls it (on the libuv threadpool) for every dns.lookup, which is what http, net, and most database drivers use. Because it goes through the OS, it honors /etc/hosts, /etc/nsswitch.conf, /etc/resolv.conf, and search domains, exactly like any other process on the machine. ENOTFOUND maps to the resolver reporting that the name has no address records. The hostname printed in the error is the literal string the code tried to resolve, which makes it your single best clue.

Common causes

  • A typo or a wrong value in configuration, including the classic getaddrinfo ENOTFOUND undefined when an env var was never set.
  • The DNS record genuinely does not exist: never created, deleted, or created in the wrong zone or wrong environment.
  • The record exists publicly but the container or VM uses a resolver that cannot see it, such as a private zone not attached to the VPC.
  • Container resolv.conf problems: an empty or wrong nameserver, or search domains that no longer match after a move between clusters or namespaces.
  • Service discovery misuse: a Docker Compose or Kubernetes service name used from outside the network where that name exists, or a service name without its namespace.

How to fix it

STABILIZE first. If a production service is failing on a name you know the correct IP for, you can pin it in /etc/hosts (or the container’s hosts file) to restore traffic while you fix resolution properly. Treat it as a tourniquet and remove it after.

echo "10.0.4.17 api.internal.example.com" | sudo tee -a /etc/hosts

DIAGNOSE. Work from the exact string in the error outward.

  1. Read the hostname in the error, character by character. If it says undefined, null, or has a stray port stuck to it like api.example.com:443, the bug is in configuration or code, not DNS. Confirm what the process actually received:
node -e "console.log(JSON.stringify(process.env.API_HOST))"
kubectl exec deploy/myapp -- printenv | grep -i host
  1. Test resolution the same way the app does. getent uses getaddrinfo, so it follows hosts file, nsswitch, and search domains exactly like Node will:
getent hosts api.internal.example.com

No output and a non-zero exit code reproduces the ENOTFOUND. Now compare with a direct DNS query, which skips all the local machinery:

dig api.internal.example.com A +short
nslookup api.internal.example.com

If dig finds the record but getent does not, the fault is local: resolv.conf, search domains, or the hosts file. If dig also finds nothing, the record is missing from the zone this resolver sees.

  1. Run the test from where the app runs. Resolution differs per network namespace, so testing from your laptop proves nothing about a container:
docker exec -it mycontainer getent hosts api.internal.example.com
kubectl exec -it deploy/myapp -- getent hosts api.internal.example.com
cat /etc/resolv.conf   # inside the container

In Kubernetes, resolv.conf will show a nameserver (the cluster DNS service IP), search domains like mynamespace.svc.cluster.local svc.cluster.local cluster.local, and options ndots:5. A cross-namespace service must be addressed as service.namespace at minimum, because the first search domain only covers the pod’s own namespace.

FIX. Match the fix to what you found:

  • Wrong or unset configuration: set the env var or config value, redeploy, and add startup validation that fails fast with a clear message when a required hostname is missing, so the next occurrence is caught in seconds.
  • Missing DNS record: create the A, AAAA, or CNAME record in the correct zone and wait for propagation. Check you are editing the zone that the failing resolver actually queries, since private and public zones for the same domain are a classic split-horizon trap.
  • Private zone not visible: attach the private hosted zone to the VPC, or point the container’s resolver at a DNS server that can see the internal zone.
  • Broken container resolv.conf: fix the nameserver or search entries at the source. In Docker that is the daemon or docker run DNS settings, in Kubernetes it is the cluster DNS (CoreDNS) and the pod’s dnsPolicy, not hand-edits inside a running container that vanish on restart.
  • Service discovery scope: use the service name only from inside the network that defines it. From another Compose project or from the host, use a published port and a real hostname. Across Kubernetes namespaces, use service.namespace or the full service.namespace.svc.cluster.local.

Then confirm end to end from the app’s own environment:

kubectl exec -it deploy/myapp -- node -e "require('dns').lookup('api.internal.example.com', console.log)"

How to prevent it

  • Validate required hostnames and URLs at process startup and crash loudly with the variable name if one is missing or malformed.
  • Test name resolution from inside the deployment environment in CI or a smoke test, not just from developer machines.
  • Keep internal names in one authoritative place (a private zone or cluster DNS) instead of scattering /etc/hosts entries that drift.
  • When renaming services or namespaces, grep configuration for the old hostname before deleting the old record.
  • Alert on a spike of ENOTFOUND or EAI_AGAIN errors in application logs, because a resolver or zone problem usually hits many services at once.

When to call a senior engineer

Call for help when resolution works in one environment and silently fails in another and you cannot see why, when split-horizon DNS or VPC private zones are involved, or when ENOTFOUND errors come and go under load and you suspect the resolver itself. Erzon engineers can trace a lookup from the application call through nsswitch, resolv.conf, and the DNS hierarchy, find the layer that lies, and leave your name resolution boring again.

Related errors we fix

Still down after this?

Want a senior engineer to just fix it?

Paste this exact error into the form. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.

Book a fix

← Back to all error fixes

Still down?

Get a senior engineer on it now

Leave your email and a line about what is happening. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.

Or email [email protected]. Same engineers, same one-hour clock.