Redis Connection Refused (ECONNREFUSED) (tested)

ECONNREFUSED means the TCP connection itself was rejected: either nothing is listening on that host and port, or a firewall actively refused it. It happens before Redis ever sees a command, so it is different from an auth error. We measured three clients (ioredis, redis, redis-cli) against a closed port and against a real Redis container we stopped and restarted mid-test.

1. What ECONNREFUSED means

ECONNREFUSED is an operating-system level TCP error, not a Redis error. The kernel on the target host received a SYN packet for a port with no process listening on it, and answered with a reset instead of a handshake. Redis never ran, Redis crashed, Redis is listening on a different port, or something else (a stale container, a reused port) is in the way.

This is distinct from an authentication failure. If Redis is up and listening but rejects your command, you get a Redis-level reply like NOAUTH, not a connection error. We measured both, see section 5.

2. Our test setup

We ran a real Redis 7.4.11 container (redis:7-alpine) via docker run --name forever-redistest -p 6380:6379 redis:7-alpine for the happy path and the live-reconnect test. For the closed-port tests we pointed clients at port 6381, which nothing was listening on.

$ docker run --rm -d --name forever-redistest -p 6380:6379 redis:7-alpine
$ docker exec forever-redistest redis-cli ping
PONG

Happy path confirmed first: ioredis against the live container fired connect then ready, and PING returned PONG.

3. The exact errors, three clients, same closed port

ClientError codeExact messageWhat happens without custom handling
ioredis 6.0.0ECONNREFUSEDconnect ECONNREFUSED 127.0.0.1:6381Emits a repeated 'error' event, auto-retries forever by default. Does not throw or crash the process.
node-redis 6.3.0 (redis package)ECONNREFUSEDconnect ECONNREFUSED 127.0.0.1:6381Same: repeated 'error' events, built-in auto-retry, client.connect()'s promise stays pending while it keeps trying. No crash.
redis-cli (bundled in redis:7-alpine)n/a (CLI text)Could not connect to Redis at 127.0.0.1:6381: Connection refusedPrints the message, exits with code 1. One attempt, no retry.

Both Node clients behave the same way under default settings: an unhandled 'error' listener would otherwise crash the process on the first attempt, but once you attach .on('error', ...), the client just keeps retrying in the background and never throws. We counted the retries for ioredis with no custom retryStrategy: 6 error events in 3 seconds, with growing gaps (4ms, 161ms, 410ms, 693ms, 1157ms, 2148ms after the first). That matches ioredis's documented default retryStrategy of Math.min(times * 50, 2000) ms between attempts, retried indefinitely unless you return null from your own strategy or call .disconnect().

4. Live test: stop the container, watch the client, restart it

We connected ioredis to the real container on port 6380, pinged it every 500 ms, then ran docker stop forever-redistest mid-loop, waited 4 seconds, then started a fresh container on the same port, with no code changes or reconnect call in between.

[+2521ms] ping #5 -> PONG
[+3029ms] event:close
[+3030ms] event:reconnecting, delay= 150
[+3183ms] event:error ECONNREFUSED "connect ECONNREFUSED 127.0.0.1:6380"
...
[+6855ms] event:reconnecting, delay= 3292
[+10150ms] event:connect
[+10153ms] event:ready
[+10154ms] ping #6 -> PONG

The moment the container stopped, ioredis fired close, then kept retrying with growing delays (150ms, 281ms, 347ms, 424ms, 814ms, 1795ms, 3292ms between tries). As soon as the new container was listening again, the very next retry succeeded: connect and ready fired and PING started returning PONG again, about 3.1 seconds after the container came back. We wrote zero reconnect logic; ioredis's default behaviour recovered on its own.

5. NOAUTH is a different error, not ECONNREFUSED

We set requirepass on the live container (redis-cli config set requirepass testpass123) and connected without credentials, to confirm this is a different failure mode than a refused connection.

ClientResult
redis-cliNOAUTH Authentication required. (exit 0 for the PING attempt itself; the reply is the error)
ioredisRejects with a ReplyError: NOAUTH HELLO must be called with the client already authenticated, otherwise the HELLO <proto> AUTH <user> <pass> option can be used to authenticate the client and select the RESP protocol version at the same time

The TCP connection succeeded in both cases; Redis answered immediately with a Redis-protocol error, not a refused socket. If you see NOAUTH or WRONGPASS, the network path is fine and the fix is credentials (requirepass / -a / the client's password option), not anything in this guide.

6. Common real causes of ECONNREFUSED

7. How to handle it

If the connection succeeds but then drops repeatedly, see ECONNRESET. For the general cross-language version of this error, see ECONNREFUSED.

Frequently asked questions

What does ECONNREFUSED mean for Redis specifically?

Nothing answered on that host and port. The OS sent back a TCP reset instead of completing the handshake. We measured this by pointing ioredis, node-redis and redis-cli at a closed port: all three got ECONNREFUSED, none got a Redis-level reply, because Redis never saw the request.

Will my Node app crash when Redis is unreachable?

Only if you have no 'error' listener on the client. With one attached, we measured that both ioredis and node-redis just keep emitting 'error' events and retrying in the background by default; they don't throw or exit the process.

Does ioredis reconnect automatically when Redis comes back?

Yes, by default, with no code required. In our live test we stopped a running Redis container mid-session and restarted it 4 seconds later; ioredis kept retrying with growing delays and reconnected on its own about 3 seconds after the new container started listening.

Is NOAUTH the same problem as connection refused?

No. We measured NOAUTH by setting a password on a live container and connecting without one: the TCP connection succeeded and Redis replied with 'NOAUTH Authentication required.' That means the network path is fine; the fix is credentials, not anything related to ECONNREFUSED.

Redis is definitely running — why do I still get ECONNREFUSED?

The most common reasons we didn't have to simulate: wrong port (6379 vs a custom one), the app and Redis sitting in different Docker networks, or Redis bound to 127.0.0.1 while the client connects from elsewhere. Run redis-cli -h HOST -p PORT ping from the same place your app runs to isolate it.

Written with AI assistance. Measured on 2026-10-02 with Node.js 24.21.0, ioredis 6.0.0, node-redis (the "redis" package) 6.3.0, against a throwaway Redis 7.4.11 (redis:7-alpine, official image) container run via Docker. redis-cli is the one bundled in that same image. The "different Docker network" cause in section 6 is reasoned from how Docker networking works, not separately measured. PlainHeaders is our extension; curl, Node.js, Docker and redis-cli are free.