redis/redis-py · critical · RedisClusterException
Redis Cluster cannot be connected. Please provide at least…
Error message
Redis Cluster cannot be connected. Please provide at least one reachable node: {str(exception)} What it means
Raised at the end of initialize() when none of the startup nodes (plus any additional_startup_nodes) could be contacted. The original connection exception is included so you can see the underlying socket/auth/timeout cause.
Solutions
- Confirm network reachability: telnet/nc to host:port from the client host.
- Verify host and port values and that the cluster nodes are actually running.
- Check credentials: if AUTH is required, pass password=/credential_provider= matching the cluster's ACL.
- For TLS clusters, ensure ssl=True and correct ca_certs; for plaintext, ensure ssl is not forced.
- Inspect str(exception) in the message for the real cause (timeout vs auth vs connection refused).
Example fix
// before rc = RedisCluster(host='redis-prod', port=6379) # wrong host/port // after rc = RedisCluster(host='redis-prod', port=7000, password=os.environ['REDIS_PW']) # verify first: # nc -zv redis-prod 7000
Defensive patterns
Strategy: try-catch
Validate before calling
import socket
def reachable(host, port, timeout=2):
try:
with socket.create_connection((host, port), timeout=timeout):
return True
except OSError:
return False
if not all(reachable(h, p) for h, p in seeds):
raise RuntimeError('Some cluster seed nodes unreachable')
rc = RedisCluster(startup_nodes=[ClusterNode(h, p) for h, p in seeds]) Type guard
null
Try / catch
from redis.exceptions import RedisClusterException
import asyncio
for attempt in range(5):
try:
await rc.initialize()
break
except RedisClusterException as e:
if 'cannot be connected' not in str(e):
raise
await asyncio.sleep(min(2 ** attempt, 30))
else:
raise Prevention
- Pre-flight check TCP reachability to every seed host:port.
- Verify AUTH/ACL credentials match the cluster before constructing RedisCluster.
- Confirm TLS settings (ssl/ca_certs) match the endpoint.
- Read the embedded str(exception) to distinguish auth vs network vs timeout.
When it happens
Trigger: All startup_nodes are unreachable: wrong host/port, network partition, firewall, TLS mismatch, auth failure, or every node is down. startup_nodes_reachable stays False and the last exception bubbles up.
Common situations: DNS resolving to a dead endpoint; security group / firewall blocking the port; AUTH/ACL password wrong so every node rejects the connection; client pointed at the wrong environment.
Related errors
- All slots are not covered after query all startup_nodes.
- Argument 'db' must be 0 or None in cluster mode
- Cluster mode is not enabled on this node
- Redis Cluster cannot be connected. Please provide at least…
- RedisCluster requires at least one node to discover the…
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/696b74c00465c3af.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/cluster.py:2372
)
if len(disagreements) > 5:
raise RedisClusterException(
f"startup_nodes could not agree on a valid "
f"slots cache: {', '.join(disagreements)}"
)
# Validate if all slots are covered or if we should try next startup node
fully_covered = True
for i in range(REDIS_CLUSTER_HASH_SLOTS):
if i not in tmp_slots:
fully_covered = False
break
if fully_covered:
break
if not startup_nodes_reachable:
raise RedisClusterException(
f"Redis Cluster cannot be connected. Please provide at least "
f"one reachable node: {str(exception)}"
) from exception
# Check if the slots are not fully covered
if not fully_covered and self.require_full_coverage:
# Despite the requirement that the slots be covered, there
# isn't a full coverage
raise RedisClusterException(
f"All slots are not covered after query all startup_nodes. "
f"{len(tmp_slots)} of {REDIS_CLUSTER_HASH_SLOTS} "
f"covered..."
)
# Set the tmp variables to the real variables
self.set_nodes(self.nodes_cache, tmp_nodes_cache, remove_old=True)
# tmp_slots was built from CLUSTER SLOTS responses and can contain
# newly-created ClusterNode objects for nodes we already know about.View on GitHub (pinned to 6a6b581b48)