redis/node-redis · error · Error
All ports are in use
Error message
All ports are in use
What it means
portIterator is a module-singleton async generator that yields free TCP ports from 6379 to 65534, checking each via isPortAvailable (a connect attempt that returns true on ECONNREFUSED). When the loop exhausts the range with every port occupied, it throws. Note: once the generator throws it becomes closed, so subsequent .next() calls return {done:true, value:undefined} rather than re-throwing — callers then fail later with an undefined-port error.
Source
Thrown at packages/test-utils/lib/dockers.ts:42
await once(socket, 'connect');
socket.end();
} catch (err) {
if (err instanceof Error && (err as ErrorWithCode).code === 'ECONNREFUSED') {
return true;
}
}
return false;
}
const portIterator = (async function* (): AsyncIterableIterator<number> {
for (let i = 6379; i < 65535; i++) {
if (await isPortAvailable(i)) {
yield i;
}
}
throw new Error('All ports are in use');
})();
interface RedisServerDockerConfig {
image: string;
version: string;
}
interface SentinelConfig {
mode: "sentinel";
mounts: Array<string>;
port: number;
}
interface ServerConfig {
mode: "server";
}
export type RedisServerDockerOptions = RedisServerDockerConfig & (SentinelConfig | ServerConfig)View on GitHub (pinned to 90fd0652bc)
Solutions
- Remove leaked containers: docker rm -f $(docker ps -aq) or docker ps then remove the redis/test images
- Stop other local services occupying ports in the 6379+ range (local redis-server, postgres, etc.)
- Reduce parallelism / worker count in the test runner so fewer ports are needed at once
Example fix
# before — ports exhausted, error thrown # (leaked containers from a prior run) # after — reclaim ports docker rm -f $(docker ps -aq --filter 'ancestor=redislabs/client-libs-test') # rerun the suite
Defensive patterns
Strategy: validation
Validate before calling
import { createConnection } from 'node:net';
async function countFreePorts(from = 6379, to = 65535, sample = 50): Promise<number> {
let free = 0;
for (let p = from; p < to && free < sample; p++) {
try {
const s = createConnection({ port: p });
await new Promise((res, rej) => { s.once('connect', () => { s.end(); res(null); }); s.once('error', rej); });
} catch { free++; }
}
return free;
} Try / catch
try {
const docker = await spawnRedisServerDocker(opts, args);
} catch (e) {
if (e instanceof Error && /All ports are in use/.test(e.message)) {
}
throw e;
} Prevention
- Add a global before() hook that runs docker rm -f on leaked test containers
- Cap test parallelism so the port range is not exhausted
- Stop local services squatting on the 6379+ range before running the suite
When it happens
Trigger: Running the test suite with many concurrent Docker containers, or leaving leaked Redis containers bound to host ports (the suite uses --network host), until the entire 6379–65534 range is occupied.
Common situations: A previous test run crashed without cleanup, leaving containers alive; CI runners with low port hygiene; many parallel test workers each consuming ports; another service (local Redis, dev DBs) squatting on the low range.
Related errors
- docker run error - ${stderr}
- docker rm error - ${stderr}
- Failed to read ${filePath} from container: ${stderr}
- TLS certificates not available after ${maxWaitMs}ms
- Invalid JSON configuration: ${error}
AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11).
Data as JSON: /api/errors/e1a703e3375204be.
Report an issue: GitHub.