redis/redis-py · error · ValueError
Cluster client has no nodes - cannot create health check cli
Error message
Cluster client has no nodes - cannot create health check client
What it means
Raised by `AbstractHealthCheckPolicy.get_client()` (redis/asyncio/multidb/healthcheck.py:209) when the active database wraps a cluster client (`AsyncRedisCluster`/`SyncRedisCluster`) but `database.client.startup_nodes` is empty. Without a startup node the policy cannot construct a health-check `AsyncRedisCluster`, so it aborts with ValueError before attempting any probe.
Source
Thrown at redis/asyncio/multidb/healthcheck.py:209
# different names (``_require_full_coverage`` vs
# ``require_full_coverage``), so resolve it defensively to
# support a sync RedisCluster underlying client too.
require_full_coverage = getattr(
nodes_manager,
"require_full_coverage",
getattr(nodes_manager, "_require_full_coverage", True),
)
client = AsyncRedisCluster(
host=first_node.host,
port=first_node.port,
dynamic_startup_nodes=nodes_manager._dynamic_startup_nodes,
address_remap=nodes_manager.address_remap,
require_full_coverage=require_full_coverage,
retry=database.client.retry,
**filtered_kwargs,
)
else:
raise ValueError(
"Cluster client has no nodes - cannot create health check client"
)
else:
raise TypeError(f"Unsupported client type: {type(database.client)}")
self._clients[db_id] = client
return client
async def close(self) -> None:
"""Close all health check clients."""
close_tasks = [
asyncio.create_task(client.aclose()) for client in self._clients.values()
]
if close_tasks:
await asyncio.gather(*close_tasks, return_exceptions=True)
self._clients.clear()View on GitHub (pinned to da03cdc7e8)
Solutions
- Ensure the RedisCluster client for that database is constructed with at least one node: `RedisCluster(host='...', port=16379)` or `startup_nodes=[ClusterNode(...)]`.
- Validate `len(client.startup_nodes) > 0` before adding the database via `add_database()` or in `DatabaseConfig`.
- If using `from_url`, supply a valid `redis://host:port` cluster URL.
Example fix
# before
cluster = RedisCluster() # no nodes
client = MultiDBClient(MultiDbConfig(
databases_config=[DatabaseConfig(client_kwargs={'__init__': {}})],
client_class=RedisCluster,
))
# after
cluster = RedisCluster(host='cluster-host', port=16379)
# or via DatabaseConfig.from_url='redis://cluster-host:16379/0'
client = MultiDBClient(MultiDbConfig(
databases_config=[DatabaseConfig(from_url='redis://cluster-host:16379/0')],
client_class=RedisCluster,
)) Defensive patterns
Strategy: validation
Validate before calling
def cluster_has_nodes(database) -> bool:
client = database.client
return bool(getattr(client, 'startup_nodes', None))
# validate before adding the database / triggering health checks Type guard
import redis.asyncio as aioredis
def is_cluster_with_nodes(database) -> bool:
c = database.client
return isinstance(c, (aioredis.RedisCluster,)) and bool(getattr(c, 'startup_nodes', None)) Try / catch
try:
await client.initialize()
except ValueError as e:
if 'no nodes' in str(e):
# fix DatabaseConfig to include a host/startup_nodes, then re-init
...
raise Prevention
- Always construct RedisCluster with `host=`/`port=` or `startup_nodes=[...]`.
- Validate `len(client.startup_nodes) > 0` before wrapping a cluster client in MultiDBClient.
- In tests, point the cluster client at a real testcontainer cluster, not an empty constructor.
When it happens
Trigger: A DatabaseConfig whose client is a RedisCluster constructed without any startup nodes (e.g. `RedisCluster()` with no `host`/`startup_nodes`), then triggering the first health check which calls `get_client()` for that database.
Common situations: Misconstructed RedisCluster — passing only `cluster_kwargs` without a host or startup_nodes; cluster client whose node list was cleared; copy/paste config error omitting the endpoint.
Related errors
- Initial health check failed. Initial health check policy: {s
- Unsupported client type: {type(database.client)}
- Argument 'db' must be 0 or None in cluster mode
- Unix domain socket is not supported in cluster mode
- RedisCluster requires at least one node to discover the clus
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/592b7d9c2c5d9b4a.json.
Report an issue: GitHub.