redis/redis-py · error · SlotNotCoveredError
Slot " " is not covered by the cluster.
Error message
Slot "{slot}" is not covered by the cluster. What it means
Raised by get_node_from_key when the computed key_slot has no entry in the slots cache — i.e. no node is known to own that hash slot. SlotNotCoveredError subclasses RedisClusterException. Typically a symptom that topology discovery has not run, is stale, or the cluster genuinely has uncovered slots (require_full_coverage=False).
Solutions
- Trigger discovery first: run any cluster command (e.g. await client.cluster_nodes()) or call client.get_nodes() before get_node_from_key.
- If slots can legitimately be uncovered, handle SlotNotCoveredError and retry after a refresh.
- Ensure require_full_coverage=True (default) for clusters that should cover all 16384 slots.
Example fix
// before
node = client.get_node_from_key('user:42')
// after
await client.cluster_nodes() # ensure topology is populated
node = client.get_node_from_key('user:42') Defensive patterns
Strategy: validation
Validate before calling
await client.cluster_nodes() # force topology discovery
slot = client.keyslot(key)
if client.nodes_manager.slots_cache.get(slot) is None:
raise ValueError(f'slot {slot} for key {key!r} not covered')
node = client.get_node_from_key(key) Type guard
def slot_is_covered(client, key) -> bool:
return client.nodes_manager.slots_cache.get(client.keyslot(key)) is not None Try / catch
from redis.exceptions import SlotNotCoveredError
for _ in range(max_attempts):
try:
node = client.get_node_from_key(key)
break
except SlotNotCoveredError:
await client.cluster_nodes() # refresh topology
else:
raise Prevention
- Trigger discovery (any cluster command) before manual key->node routing.
- Handle SlotNotCoveredError by refreshing topology and retrying.
When it happens
Trigger: Calling get_node_from_key(key) before the initial CLUSTER NODES/SLOTS discovery populated slots_cache; calling it right after construction without any command having triggered discovery; a cluster with require_full_coverage=False where some slots have no owner.
Common situations: Using get_node_from_key for manual routing without first issuing a command that triggers topology refresh; cluster still forming/scaling; slots_cache evicted after a failed rediscovery.
Related errors
- No targets were found to execute
- No targets were found to execute
- No targets were found to execute
- startup_nodes could not agree on a valid slots cache
- All slots are not covered after query all startup_nodes.
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/0351ff9fbc646e6f.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/cluster.py:846
def get_node_from_key(
self, key: str, replica: bool = False
) -> Optional["ClusterNode"]:
"""
Get the cluster node corresponding to the provided key.
:param key:
:param replica:
| Indicates if a replica should be returned
|
None will returned if no replica holds this key
:raises SlotNotCoveredError: if the key is not covered by any slot.
"""
slot = self.keyslot(key)
slot_cache = self.nodes_manager.slots_cache.get(slot)
if not slot_cache:
raise SlotNotCoveredError(f'Slot "{slot}" is not covered by the cluster.')
if replica:
if len(self.nodes_manager.slots_cache[slot]) < 2:
return None
node_idx = 1
else:
node_idx = 0
return slot_cache[node_idx]
def get_random_primary_or_all_nodes(self, command_name):
"""
Returns random primary or all nodes depends on READONLY mode.
"""
if self.read_from_replicas and command_name in READ_COMMANDS:
return self.get_random_node()
return self.get_random_primary_node()View on GitHub (pinned to 6a6b581b48)