Skip to content
Latchkey

ioredis / node-redis "connect ECONNREFUSED 127.0.0.1:6379" in CI

The Node Redis client (ioredis or node-redis) attempted a TCP connect to 127.0.0.1:6379 and the OS returned ECONNREFUSED. Either nothing is listening yet, or the Redis service is reachable at a different host than 127.0.0.1 in this job.

What this error means

A Jest or Vitest suite or a server start fails with "Error: connect ECONNREFUSED 127.0.0.1:6379" and a stack pointing into ioredis or @redis/client. ioredis then retries with "reconnect on error".

node
Error: connect ECONNREFUSED 127.0.0.1:6379
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1595:16) {
  errno: -111, code: 'ECONNREFUSED', address: '127.0.0.1', port: 6379
}

Common causes

Redis service not up when the client connected

ioredis connects eagerly at construction; if the service container is still booting, the first connect is refused.

Container job needs the service name, not 127.0.0.1

When the job runs inside a container, 127.0.0.1 is that container, not the Redis service. The host must be the service alias redis.

How to fix it

Use REDIS_URL and wait for readiness

  1. Read the connection from REDIS_URL so the host is configurable.
  2. Set REDIS_URL to the service name on container jobs.
  3. Gate the suite on a service health check so the port is open first.
test/setup.ts
import Redis from 'ioredis';
const client = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
await client.ping();

Set the URL per job model

On a container job the URL host is the service name; on a runner-host job it is localhost with the mapped port.

.github/workflows/ci.yml
env:
  REDIS_URL: redis://redis:6379

How to prevent it

  • Drive the client from REDIS_URL, never a hard-coded 127.0.0.1.
  • Wait for the Redis health check before opening the client.
  • On container jobs, connect by service name on the Docker network.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →