Revision 1 — the current text. The evidence on this page is this revision’s own — it has not been carried forward from, or to, any other revision.
Diagnosing Node.js ECONNREFUSED
Confirms nothing is actually listening at the target address, then splits between a host/port misconfiguration (wrong address for where the dependency actually lives) and a startup-order race (the app connects before its dependency is ready). It does not cover connection timeouts (ETIMEDOUT), which point at network reachability rather than an actively refused connection, and it isn't specific to any one dependency — the same triage applies whether the target is a database, cache, or another service.
Node process crashes or logs an unhandled error containing ECONNREFUSED
Error includes a specific host:port, e.g. ECONNREFUSED 127.0.0.1:5432
Happens reliably right after deploy or container start, or intermittently under restarts
The diagnostic path
8 steps, exactly as this revision published them.
Step 1 · StartNode process throws ECONNREFUSED
ECONNREFUSED means the TCP handshake reached the target host and was actively rejected (an RST) — nothing is listening on that exact port there right now. This narrows the cause to three things: nothing's listening yet, the app is connecting to the wrong host/port, or the thing that should be listening crashed.
What happens next
passed → step 2, Is anything currently listening at that exact host and port?
Step 2 · TestIs anything currently listening at that exact host and port?
Check on the target host itself (locally, in the container, or via the orchestrator) whether the address the error names is actually bound by anything right now.
Read-onlysh
ss -ltnp | grep <port>
Expected result
(no output)
What happens next
passed → step 3, Does the app's configured address actually match where the dependency lives?
failed → step 4, Something is listening there right now
unknown → step 3, Does the app's configured address actually match where the dependency lives?
Step 3 · TestDoes the app's configured address actually match where the dependency lives?
Print the resolved connection config the process is actually using and compare it against where the dependency really runs — a classic mismatch is a config pointing at localhost/127.0.0.1 when the dependency is actually a separate container or pod reachable only by its own service name.
Read-onlysh
node -e "console.log(process.env.DATABASE_URL)"
Expected result
postgres://app:***@127.0.0.1:5432/app
What happens next
passed → step 5, Root cause: wrong host/port for where the dependency actually runs
failed → step 6, Did the dependency actually finish starting, or has it crashed?
unknown → step 6, Did the dependency actually finish starting, or has it crashed?
Step 4 · EndSomething is listening there right now
A plain ECONNREFUSED shouldn't be reproducible any more if something is actively listening at that address. This was probably transient — the service was mid-restart at the exact moment of connection — or the error being chased is stale. Re-run the failing call and see if it recurs.
Step 5 · Root causeRoot cause: wrong host/port for where the dependency actually runs
The configured address doesn't match where the dependency lives — for example use the Docker Compose service name instead of localhost, or the Kubernetes Service DNS name (<service>.<namespace>.svc.cluster.local) instead of 127.0.0.1. The exact fix is app/environment specific from here.
Step 6 · TestDid the dependency actually finish starting, or has it crashed?
The configured address genuinely matches where the dependency should be — check the dependency's own logs/status rather than the connecting app's.
failed → step 8, Dependency believes it's listening but still refuses this app
unknown → step 8, Dependency believes it's listening but still refuses this app
Step 7 · Root causeRoot cause: startup-order race
The dependency isn't running yet, is still starting, or crashed — the Node app tried to connect before it was actually accepting connections. The robust fix is retrying the connection with backoff on the Node side; the alternative is an explicit startup dependency, such as Compose's depends_on with a healthcheck condition, or a Kubernetes init container that waits for the dependency to be ready.
Step 8 · EndDependency believes it's listening but still refuses this app
The dependency's own logs say it started and is listening, yet this app still gets refused — check that it's actually listening on the interface the app connects through (a service bound only to 127.0.0.1 inside its own container refuses connections from other containers/pods, which need it bound to 0.0.0.0), and that both sides are on the same Docker network / Kubernetes namespace with an actual route between them.
What would strengthen it: 6 more independent reproductions. Reproductions from 3 more distinct environments.
This counts only what was recorded against revision 1 itself. Nothing reported against another revision is included here — see the revision history for why.