{"id":"eaed14af67536dfb","repo":"redis/redis-py","slug":"slot-slot-not-covered-by-the-cluster-require","errorCode":null,"errorMessage":"Slot \"{slot}\" not covered by the cluster. \"require_full_coverage={self.require_full_coverage}\"","messagePattern":"Slot \"(.+?)\" not covered by the cluster\\. \"require_full_coverage=(.+?)\"","errorType":"exception","errorClass":"SlotNotCoveredError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/cluster.py","lineNumber":2204,"sourceCode":"        self,\n        slot: int,\n        read_from_replicas: bool = False,\n        load_balancing_strategy=None,\n    ) -> \"ClusterNode\":\n        if read_from_replicas is True and load_balancing_strategy is None:\n            load_balancing_strategy = LoadBalancingStrategy.ROUND_ROBIN\n\n        try:\n            if len(self.slots_cache[slot]) > 1 and load_balancing_strategy:\n                # get the server index using the strategy defined in load_balancing_strategy\n                primary_name = self.slots_cache[slot][0].name\n                node_idx = self.read_load_balancer.get_server_index(\n                    primary_name, len(self.slots_cache[slot]), load_balancing_strategy\n                )\n                return self.slots_cache[slot][node_idx]\n            return self.slots_cache[slot][0]\n        except (IndexError, TypeError):\n            raise SlotNotCoveredError(\n                f'Slot \"{slot}\" not covered by the cluster. '\n                f'\"require_full_coverage={self.require_full_coverage}\"'\n            )\n\n    def get_nodes_by_server_type(self, server_type: str) -> List[\"ClusterNode\"]:\n        return [\n            node\n            for node in self.nodes_cache.values()\n            if node.server_type == server_type\n        ]\n\n    async def initialize(\n        self,\n        additional_startup_nodes_info: Optional[List[Tuple[str, int]]] = None,\n        last_failed_node_name: Optional[str] = None,\n    ) -> None:\n        self.read_load_balancer.reset()\n        tmp_nodes_cache: Dict[str, \"ClusterNode\"] = {}","sourceCodeStart":2186,"sourceCodeEnd":2222,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/cluster.py#L2186-L2222","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Trigger a topology refresh and retry: await rc.reload_exception() / await rc.refresh_table_nodes() or re-create the client.","If running with require_full_coverage=False knowingly, ensure app code avoids uncovered slots or handle SlotNotCoveredError with a refresh+retry.","For long-lived clients, enable the cluster's topology auto-refresh so stale slots are repopulated automatically."],"exampleFix":"// before\ntry:\n    await rc.get('user:42')\nexcept SlotNotCoveredError:\n    pass\n\n// after\ntry:\n    await rc.get('user:42')\nexcept SlotNotCoveredError:\n    await rc.reload_exception()\n    await rc.get('user:42')","handlingStrategy":"retry","validationCode":"from redis.cluster import SlotNotCoveredError\n\nasync def get_covered(rc, key):\n    slot = rc.keyslot(key)\n    try:\n        node = rc.nodes_manager.get_node_from_slot(slot, rc.read_from_replicas)\n    except SlotNotCoveredError:\n        await rc.reload_exception()\n        node = rc.nodes_manager.get_node_from_slot(slot, rc.read_from_replicas)\n    return node","typeGuard":"from redis.asyncio.cluster import RedisCluster\n\ndef slot_is_covered(rc: RedisCluster, slot: int) -> bool:\n    nodes = rc.nodes_manager.slots_cache.get(slot)\n    return bool(nodes)","tryCatchPattern":"from redis.cluster import SlotNotCoveredError\n\nfor attempt in range(3):\n    try:\n        return await rc.get(key)\n    except SlotNotCoveredError:\n        await rc.reload_exception()\nraise RuntimeError('slot still uncovered after topology refresh')","preventionTips":["Keep require_full_coverage=True (default) so the client fails fast at startup rather than mid-request.","Wrap cluster commands in a retry helper that refreshes topology on SlotNotCoveredError.","Avoid running clients during active resharding, or schedule a topology refresh afterwards."],"tags":["redis-cluster","slot-coverage","topology","resharding"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}