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

  1. Ensure the RedisCluster client for that database is constructed with at least one node: `RedisCluster(host='...', port=16379)` or `startup_nodes=[ClusterNode(...)]`.
  2. Validate `len(client.startup_nodes) > 0` before adding the database via `add_database()` or in `DatabaseConfig`.
  3. 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

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


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/592b7d9c2c5d9b4a.json. Report an issue: GitHub.