redis/redis-py · critical · RedisClusterException

All slots are not covered after query all startup_nodes. {le

Error message

All slots are not covered after query all startup_nodes. {len(tmp_slots)} of {REDIS_CLUSTER_HASH_SLOTS} covered...

What it means

Raised after initialize() queried all reachable startup nodes and the merged slots cache still does not cover all REDIS_CLUSTER_HASH_SLOTS (16384), but only when require_full_coverage=True (the default). The client refuses to operate with partial coverage because some keys' slots would have no owning node, causing unpredictable routing failures later.

Source

Thrown at redis/asyncio/cluster.py:2380

                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.
            # Rebuild the slots cache with the preserved nodes_cache instances
            # so existing per-node connection pools stay in use after refresh.
            # Keep the shared node-list-per-slot-range shape from tmp_slots to
            # avoid allocating a separate list for every slot.
            node_lists_by_id: Dict[int, List["ClusterNode"]] = {}
            new_slots_cache: Dict[int, List["ClusterNode"]] = {}
            for slot, nodes in tmp_slots.items():
                node_list_id = id(nodes)
                slot_nodes = node_lists_by_id.get(node_list_id)

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Ensure all nodes (especially primaries) are up and reachable, then retry client creation.
  2. If partial coverage is acceptable for your workload, construct with require_full_coverage=False (note: uncovered slots will then raise SlotNotCoveredError at runtime).
  3. Wait for the cluster to report cluster_state:ok (redis-cli CLUSTER INFO) before connecting.

Example fix

// before
rc = RedisCluster(host='seed', port=6379)  # partial coverage, default True

// after
rc = RedisCluster(host='seed', port=6379, require_full_coverage=False)
Defensive patterns

Strategy: validation

Validate before calling

import redis.asyncio as aioredis

async def cluster_slot_coverage(host, port) -> tuple[int, int]:
    r = aioredis.Redis(host=host, port=port)
    try:
        slots = await r.cluster_slots()
        covered = sum((s[1] - s[0] + 1) for s in slots)
        return covered, 16384
    finally:
        await r.aclose()

covered, total = await cluster_slot_coverage(host, port)
if covered < total:
    raise RuntimeError(f'Cluster only covers {covered}/{total} slots')

Type guard

def full_coverage(covered: int, total: int = 16384) -> bool:
    return covered == total

Try / catch

from redis.cluster import RedisClusterException

try:
    rc = RedisCluster(host=h, port=p)
except RedisClusterException as e:
    if 'not covered' in str(e):
        # either wait for the cluster to heal, or allow partial coverage
        rc = RedisCluster(host=h, port=p, require_full_coverage=False)
    else:
        raise

Prevention

When it happens

Trigger: Connecting to a cluster that is missing slots (degraded, partially failed, or still being created); a cluster where some nodes are unreachable so their slots aren't represented; require_full_coverage=True (default) with an incomplete topology.

Common situations: A node owning a slot range is down during client startup; cluster creation not yet finished (slots not all assigned); flaky seed nodes returning partial CLUSTER SLOTS; connecting during maintenance/failover.

Related errors


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