redis/redis-py · error · RedisClusterException
No way to dispatch this command to Redis Cluster. Missing ke
Error message
No way to dispatch this command to Redis Cluster. Missing key.
You can execute the command by specifying target nodes.
Command: {args} What it means
Raised by _determine_slot() when a command yields zero keys (per COMMAND INFO key extraction) and is not FCALL/FCALL_RO. Redis Cluster routes by key hash slot, so a keyless command has no determinable destination. The library will not pick a random shard for arbitrary commands; the caller must name the target explicitly.
Source
Thrown at redis/asyncio/cluster.py:1013
if command.upper() in ("EVAL", "EVALSHA"):
# command syntax: EVAL "script body" num_keys ...
if len(args) < 2:
raise RedisClusterException(
f"Invalid args in command: {command, *args}"
)
keys = args[2 : 2 + int(args[1])]
# if there are 0 keys, that means the script can be run on any node
# so we can just return a random slot
if not keys:
return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS)
else:
keys = await self.commands_parser.get_keys(command, *args)
if not keys:
# FCALL can call a function with 0 keys, that means the function
# can be run on any node so we can just return a random slot
if command.upper() in ("FCALL", "FCALL_RO"):
return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS)
raise RedisClusterException(
"No way to dispatch this command to Redis Cluster. "
"Missing key.\nYou can execute the command by specifying "
f"target nodes.\nCommand: {args}"
)
# single key command
if len(keys) == 1:
return self.keyslot(keys[0])
# multi-key command; we need to make sure all keys are mapped to
# the same slot
slots = {self.keyslot(key) for key in keys}
if len(slots) != 1:
raise RedisClusterException(
f"{command} - all keys must map to the same key slot"
)
return slots.pop()View on GitHub (pinned to da03cdc7e8)
Solutions
- Pass target_nodes to name the destination: rc.execute_command('DBSIZE', target_nodes='PRIMARIES') or rc.info(target_nodes=node).
- Use a node-flag constant such as RedisCluster.PRIMARIES / RANDOM / ALL_NODES for fan-out admin commands.
- For a single-shard call, resolve the node via rc.get_node(host=..., port=...) and pass it as target_nodes.
Example fix
// before await rc.dbsize() // after await rc.dbsize(target_nodes=RedisCluster.PRIMARIES)
Defensive patterns
Strategy: validation
Validate before calling
from redis.asyncio.cluster import RedisCluster
KEYLESS_ADMIN_COMMANDS = {'INFO', 'DBSIZE', 'FLUSHDB', 'FLUSHALL', 'CONFIG', 'CLIENT', 'CLUSTER'}
async def run_keyless(rc: RedisCluster, command: str, *args, target='PRIMARIES'):
if command.upper().split()[0] in KEYLESS_ADMIN_COMMANDS:
return await rc.execute_command(command, *args, target_nodes=target)
return await rc.execute_command(command, *args) Type guard
from typing import Any
from redis.asyncio.cluster import RedisCluster
def needs_target_nodes(rc: RedisCluster, command: str) -> bool:
# Crude heuristic: commands the COMMAND parser extracts 0 keys from
keys = rc.commands_parser # ensure initialized
return command.upper() not in ('FCALL', 'FCALL_RO') Try / catch
from redis.cluster import RedisClusterException
try:
await rc.execute_command('DBSIZE')
except RedisClusterException as e:
if 'Missing key' in str(e):
await rc.execute_command('DBSIZE', target_nodes=RedisCluster.PRIMARIES)
else:
raise Prevention
- Audit standalone-Redis code ported to cluster for keyless admin commands and add target_nodes.
- Default to target_nodes=RedisCluster.PRIMARIES for fan-out admin/inspection commands.
- Keep a helper that wraps admin commands so routing is centralized.
When it happens
Trigger: Calling rc.execute_command('INFO'), rc.execute_command('DBSIZE'), rc.config_get(), rc.flushdb() etc. without target_nodes, where the command's request policy is key-based (DEFAULT_KEYED) and no key argument is present. Also triggered by custom/unknown commands the COMMAND parser cannot extract keys from.
Common situations: Porting standalone-Redis code (rc.info(), rc.dbsize()) to RedisCluster without adding target_nodes; issuing admin/inspection commands that are inherently keyless; using a command the connected server doesn't know so COMMAND INFO returns no key specs.
Related errors
- Cannot execute FT.CURSOR commands without FT.AGGREGATE
- No targets were found to execute {args} command on
- No targets were found to execute {cmd.args} command on
- No targets were found to execute {c.args} command on
- {cmd_name.upper()} command doesn't exist in Redis commands
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/e8fd64e8af38d29b.json.
Report an issue: GitHub.