{"record":{"id":"5eca4ef2a745ef16","repo":"redis/node-redis","slug":"all-the-root-nodes-are-unavailable","errorCode":null,"errorMessage":"All the root nodes are unavailable","messagePattern":"All the root nodes are unavailable","errorType":"exception","errorClass":"RootNodesUnavailableError","httpStatus":null,"severity":"critical","filePath":"packages/client/lib/cluster/cluster-slots.ts","lineNumber":338,"sourceCode":"  }\n\n  async #discoverWithRootNodes() {\n    const start = Math.floor(Math.random() * this.#options.rootNodes.length);\n    for (let i = start; i < this.#options.rootNodes.length; i++) {\n      if (!this.#isOpen) throw new Error('Cluster closed');\n      if (await this.#discover(this.#options.rootNodes[i])) {\n        return;\n      }\n    }\n\n    for (let i = 0; i < start; i++) {\n      if (!this.#isOpen) throw new Error('Cluster closed');\n      if (await this.#discover(this.#options.rootNodes[i])) {\n        return;\n      }\n    }\n\n    throw new RootNodesUnavailableError();\n  }\n\n  #resetSlots() {\n    this.slots = new Array(RedisClusterSlots.#SLOTS);\n    this.masters = [];\n    this.replicas = [];\n    this._randomNodeIterator = undefined;\n  }\n\n  async #discover(rootNode: RedisClusterClientOptions) {\n    this.clientSideCache?.clear();\n    this.clientSideCache?.disable();\n\n    try {\n      const addressesInUse = new Set<string>(),\n        promises: Array<Promise<unknown>> = [],\n        eagerConnect = this.#options.minimizeConnections !== true;\n","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/cluster/cluster-slots.ts#L320-L356","documentation":"RootNodesUnavailableError, thrown at the end of #discoverWithRootNodes after every configured root node was tried and none returned a valid cluster topology. This means initial cluster connection (or a full rediscovery) could not reach any seed node. It surfaces as a typed error so callers can distinguish 'all roots down' from a single-node failure.","triggerScenarios":"cluster.connect() where every entry in rootNodes is unreachable (wrong host/port, firewall, DNS failure, all nodes down). Also thrown on a full topology refresh if all roots are unreachable at that point.","commonSituations":"Misconfigured rootNodes host/port; Redis cluster behind a firewall/security group blocking the client; DNS not resolving cluster endpoints; all seed nodes temporarily down during a major outage; localhost vs 127.0.0.1 mismatch in containers.","solutions":["Verify each rootNode host/port is reachable from the client host (telnet/nc/redis-cli ping).","Check network ACLs, security groups, and firewall rules permit TCP to the Redis ports.","Confirm DNS resolves the rootNode hostnames and the IPs are current.","Add redundant root nodes so a single unreachable seed does not cause total failure.","Retry cluster.connect() after a backoff in case the outage is transient."],"exampleFix":"// before\nconst cluster = createCluster({ rootNodes: [{ socket: { host: 'wrong-host', port: 6379 } }] });\nawait cluster.connect(); // RootNodesUnavailableError\n\n// after\nconst cluster = createCluster({\n  rootNodes: [\n    { socket: { host: 'redis-0.cluster', port: 6379 } },\n    { socket: { host: 'redis-1.cluster', port: 6379 } }\n  ]\n});\nawait cluster.connect();","handlingStrategy":"retry","validationCode":"async function canReachRoot(host: string, port: number): Promise<boolean> {\n  try {\n    const s = await new Promise<import('net').Socket>((res, rej) => {\n      const sock = require('net').connect(port, host, () => res(sock));\n      sock.on('error', rej);\n    });\n    s.destroy();\n    return true;\n  } catch { return false; }\n}","typeGuard":"function isRootNodesUnavailable(e: unknown): boolean {\n  return e instanceof RootNodesUnavailableError;\n}","tryCatchPattern":"for (let i = 0; i < 5; i++) {\n  try {\n    await cluster.connect();\n    break;\n  } catch (e) {\n    if (e instanceof RootNodesUnavailableError) { await new Promise(r => setTimeout(r, 1000 * (i + 1))); continue; }\n    throw e;\n  }\n}","preventionTips":["Verify root node host/port reachability before connect().","Configure multiple redundant root nodes.","Check firewall/security-group rules permit TCP to Redis ports.","Retry connect() with backoff for transient outages."],"tags":["cluster","connection","network","discovery"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}