redis/redis-py · error · SlotNotCoveredError

Slot "{slot}" not covered by the cluster. "require_full_cove

Error message

Slot "{slot}" not covered by the cluster. "require_full_coverage={self.require_full_coverage}"

What it means

A SlotNotCoveredError raised by get_node_from_slot() when slots_cache[slot] is empty/missing (IndexError) or None (TypeError). This means no node in the cached cluster topology claims responsibility for that hash slot. Whether this is fatal depends on require_full_coverage: with it True the cluster should have been rejected at startup, so this usually indicates the slot map went stale mid-run (e.g. resharding or a node drop).

Source

Thrown at redis/asyncio/cluster.py:2204

        self,
        slot: int,
        read_from_replicas: bool = False,
        load_balancing_strategy=None,
    ) -> "ClusterNode":
        if read_from_replicas is True and load_balancing_strategy is None:
            load_balancing_strategy = LoadBalancingStrategy.ROUND_ROBIN

        try:
            if len(self.slots_cache[slot]) > 1 and load_balancing_strategy:
                # get the server index using the strategy defined in load_balancing_strategy
                primary_name = self.slots_cache[slot][0].name
                node_idx = self.read_load_balancer.get_server_index(
                    primary_name, len(self.slots_cache[slot]), load_balancing_strategy
                )
                return self.slots_cache[slot][node_idx]
            return self.slots_cache[slot][0]
        except (IndexError, TypeError):
            raise SlotNotCoveredError(
                f'Slot "{slot}" not covered by the cluster. '
                f'"require_full_coverage={self.require_full_coverage}"'
            )

    def get_nodes_by_server_type(self, server_type: str) -> List["ClusterNode"]:
        return [
            node
            for node in self.nodes_cache.values()
            if node.server_type == server_type
        ]

    async def initialize(
        self,
        additional_startup_nodes_info: Optional[List[Tuple[str, int]]] = None,
        last_failed_node_name: Optional[str] = None,
    ) -> None:
        self.read_load_balancer.reset()
        tmp_nodes_cache: Dict[str, "ClusterNode"] = {}

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Trigger a topology refresh and retry: await rc.reload_exception() / await rc.refresh_table_nodes() or re-create the client.
  2. If running with require_full_coverage=False knowingly, ensure app code avoids uncovered slots or handle SlotNotCoveredError with a refresh+retry.
  3. For long-lived clients, enable the cluster's topology auto-refresh so stale slots are repopulated automatically.

Example fix

// before
try:
    await rc.get('user:42')
except SlotNotCoveredError:
    pass

// after
try:
    await rc.get('user:42')
except SlotNotCoveredError:
    await rc.reload_exception()
    await rc.get('user:42')
Defensive patterns

Strategy: retry

Validate before calling

from redis.cluster import SlotNotCoveredError

async def get_covered(rc, key):
    slot = rc.keyslot(key)
    try:
        node = rc.nodes_manager.get_node_from_slot(slot, rc.read_from_replicas)
    except SlotNotCoveredError:
        await rc.reload_exception()
        node = rc.nodes_manager.get_node_from_slot(slot, rc.read_from_replicas)
    return node

Type guard

from redis.asyncio.cluster import RedisCluster

def slot_is_covered(rc: RedisCluster, slot: int) -> bool:
    nodes = rc.nodes_manager.slots_cache.get(slot)
    return bool(nodes)

Try / catch

from redis.cluster import SlotNotCoveredError

for attempt in range(3):
    try:
        return await rc.get(key)
    except SlotNotCoveredError:
        await rc.reload_exception()
raise RuntimeError('slot still uncovered after topology refresh')

Prevention

When it happens

Trigger: Operating on a key whose slot is mid-reshard (moved away but not yet assigned elsewhere in the client's cache), a degraded cluster where some slots lost their owner, or require_full_coverage=False deliberately allowing partial coverage at startup and then touching an uncovered slot.

Common situations: Active resharding/rebalancing while the app runs; a node that owned slots crashed and the client's slots cache hasn't refreshed; connecting with reinitialize_steps/setuptools that allow partial coverage; slot migration tooling leaving gaps.

Related errors


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