redis/redis-py · error · RedisClusterException
Too many targets for command {cmd.args}
Error message
Too many targets for command {cmd.args} What it means
Raised in the pipeline execute path when a single queued command resolves to more than one target node. The cluster pipeline groups commands by destination node and executes each node's batch in one round-trip; a command that fans out to multiple nodes (e.g. an ALL_NODES policy command) cannot be placed in a single per-node batch, so it is rejected.
Source
Thrown at redis/asyncio/cluster.py:2944
request_policy=client._command_flags_mapping[
command_flag
]
)
else:
command_policies = CommandPolicies()
target_nodes = await client._determine_nodes(
*cmd.args,
request_policy=command_policies.request_policy,
node_flag=passed_targets,
)
if not target_nodes:
raise RedisClusterException(
f"No targets were found to execute {cmd.args} command on"
)
cmd.command_policies = command_policies
if len(target_nodes) > 1:
raise RedisClusterException(f"Too many targets for command {cmd.args}")
node = target_nodes[0]
if node.name not in nodes:
nodes[node.name] = (node, [])
nodes[node.name][1].append(cmd)
# Start timing for observability
start_time = time.monotonic()
errors = await asyncio.gather(
*(
asyncio.create_task(node[0].execute_pipeline(node[1]))
for node in nodes.values()
)
)
# Record operation duration for each node
for node_name, (node, commands) in nodes.items():
# Find the first error in this node's commands, if anyView on GitHub (pinned to da03cdc7e8)
Solutions
- Remove fan-out commands from the pipeline; issue them separately with target_nodes=ALL_NODES / PRIMARIES.
- Pass a single ClusterNode (or single-slot key set) so the command resolves to exactly one node.
- Split the pipeline so each queued command's keys share one slot and one target.
Example fix
// before
pipe = rc.pipeline()
pipe.flushdb() # fan-out, resolves to all primaries
pipe.set('k', 'v')
await pipe.execute()
// after
pipe = rc.pipeline()
pipe.set('k', 'v')
await pipe.execute()
await rc.flushdb(target_nodes=RedisCluster.PRIMARIES) Defensive patterns
Strategy: validation
Validate before calling
FAN_OUT_COMMANDS = {'FLUSHDB', 'FLUSHALL', 'CONFIG', 'CLIENT', 'CLUSTER', 'BGSAVE', 'BGREWRITEAOF'}
def split_pipeline_commands(rc, commands):
pipe = rc.pipeline()
deferred = []
for cmd, args in commands:
if cmd.upper().split()[0] in FAN_OUT_COMMANDS:
deferred.append((cmd, args))
else:
getattr(pipe, cmd.lower())(*args)
return pipe, deferred Type guard
from redis.asyncio.cluster import ClusterNode
def command_targets_single_node(target_nodes) -> bool:
if isinstance(target_nodes, ClusterNode):
return True
if isinstance(target_nodes, list):
return len(target_nodes) <= 1
return False # flag strings like ALL_NODES are multi-target Try / catch
from redis.cluster import RedisClusterException
pipe = rc.pipeline()
pipe.flushdb()
try:
await pipe.execute()
except RedisClusterException as e:
if 'Too many targets' in str(e):
await rc.flushdb(target_nodes=RedisCluster.PRIMARIES)
else:
raise Prevention
- Keep admin/fan-out commands out of pipelines; issue them separately with target_nodes.
- Pass a single ClusterNode or single-slot keys when queueing into a pipeline.
- Review pipelined command lists for any ALL_NODES/PRIMARIES policy commands.
When it happens
Trigger: Queuing a command with an ALL_NODES/PRIMARIES request policy in a pipeline (e.g. pipe.config_get(), pipe.flushdb() with fan-out); passing target_nodes=[node1, node2] (a multi-node list) to a single pipelined command.
Common situations: Treating a cluster pipeline like a standalone pipeline and queuing admin/fan-out commands; passing a list of nodes where a single node is required; misunderstanding that pipeline commands must be single-shard.
Related errors
- shard_hint is deprecated in cluster mode
- No targets were found to execute {cmd.args} command on
- method multi() is not supported outside of transactional con
- method watch() is not supported outside of transactional con
- method unwatch() is not supported outside of transactional c
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/ad98db08b98985a6.json.
Report an issue: GitHub.