{"id":"696b74c00465c3af","repo":"redis/redis-py","slug":"redis-cluster-cannot-be-connected-please-provide","errorCode":null,"errorMessage":"Redis Cluster cannot be connected. Please provide at least one reachable node: {str(exception)}","messagePattern":"Redis Cluster cannot be connected\\. Please provide at least one reachable node: (.+?)","errorType":"exception","errorClass":"RedisClusterException","httpStatus":null,"severity":"critical","filePath":"redis/asyncio/cluster.py","lineNumber":2371,"sourceCode":"                                )\n\n                                if len(disagreements) > 5:\n                                    raise RedisClusterException(\n                                        f\"startup_nodes could not agree on a valid \"\n                                        f\"slots cache: {', '.join(disagreements)}\"\n                                    )\n\n                # Validate if all slots are covered or if we should try next startup node\n                fully_covered = True\n                for i in range(REDIS_CLUSTER_HASH_SLOTS):\n                    if i not in tmp_slots:\n                        fully_covered = False\n                        break\n                if fully_covered:\n                    break\n\n            if not startup_nodes_reachable:\n                raise RedisClusterException(\n                    f\"Redis Cluster cannot be connected. Please provide at least \"\n                    f\"one reachable node: {str(exception)}\"\n                ) from exception\n\n            # Check if the slots are not fully covered\n            if not fully_covered and self.require_full_coverage:\n                # Despite the requirement that the slots be covered, there\n                # isn't a full coverage\n                raise RedisClusterException(\n                    f\"All slots are not covered after query all startup_nodes. \"\n                    f\"{len(tmp_slots)} of {REDIS_CLUSTER_HASH_SLOTS} \"\n                    f\"covered...\"\n                )\n\n            # Set the tmp variables to the real variables\n            self.set_nodes(self.nodes_cache, tmp_nodes_cache, remove_old=True)\n            # tmp_slots was built from CLUSTER SLOTS responses and can contain\n            # newly-created ClusterNode objects for nodes we already know about.","sourceCodeStart":2353,"sourceCodeEnd":2389,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/cluster.py#L2353-L2389","documentation":"Raised at the end of initialize() when no startup node could be reached at all. The client tried every seed node, each attempt threw (connection refused, timeout, DNS failure, auth error), and the last exception is wrapped with this message. Without a single reachable node the client cannot learn the cluster topology, so construction fails.","triggerScenarios":"Wrong host/port in the URL; firewall/network ACL blocking the Redis port; all seed nodes down; TLS mismatch (redis:// vs rediss://); authentication failure (wrong password / missing ACL); DNS not resolving the cluster endpoint.","commonSituations":"Connecting from outside a VPC/security group without the port opened; stale startup_nodes list after a cluster migration; AUTH/RequirePass misconfiguration; using plain redis:// against a TLS-only endpoint.","solutions":["Verify reachability independently: telnet/nc <host> <port> or redis-cli -h <host> -p <port> PING.","Correct the scheme for TLS endpoints (rediss://) and supply the right password/credential_provider.","Refresh the startup_nodes list with currently-live nodes and check security groups/firewall rules."],"exampleFix":"// before\nrc = RedisCluster(host='redis.internal', port=6379)  # unreachable\n\n// after\n# verify connectivity first\n# redis-cli -h redis.internal -p 6379 PING  -> PONG\nrc = RedisCluster(host='redis.internal', port=6379)","handlingStrategy":"validation","validationCode":"import socket\n\ndef assert_reachable(host, port, timeout=3):\n    try:\n        with socket.create_connection((host, port), timeout=timeout):\n            pass\n    except OSError as e:\n        raise RuntimeError(f'Cannot reach {host}:{port}: {e}') from e\n\n# before constructing the client\nassert_reachable(host, port)\nrc = RedisCluster(host=host, port=port)","typeGuard":"def endpoint_is_reachable(host: str, port: int, timeout: float = 3.0) -> bool:\n    try:\n        with socket.create_connection((host, port), timeout=timeout):\n            return True\n    except OSError:\n        return False","tryCatchPattern":"from redis.cluster import RedisClusterException\n\ntry:\n    rc = RedisCluster.from_url(url)\nexcept RedisClusterException as e:\n    if 'cannot be connected' in str(e):\n        # log and surface actionable guidance\n        raise RuntimeError('All seed nodes unreachable — check host/port/firewall/TLS/auth') from e\n    raise","preventionTips":["Preflight-check TCP reachability to each seed node before constructing the client.","Match the URL scheme to the endpoint (rediss:// for TLS).","Keep the startup_nodes list current and validate credentials/ACLs in CI."],"tags":["redis-cluster","startup","network","connectivity","auth"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}