redis/redis-py · error · RedisClusterException

Too many targets for command {c.args}

Error message

Too many targets for command {c.args}

What it means

Raised in PipelineStrategy._send_cluster_commands (redis/cluster.py:4296) when _determine_nodes() returns more than one node for a single queued command. The pipeline fan-out logic expects each individual command to be pinned to exactly one node; multi-node fan-out is meant to happen at execute() time via response policies, not by handing one command a list of nodes.

Source

Thrown at redis/cluster.py:4296

                                    request_policy=self._pipe._command_flags_mapping[
                                        command_flag
                                    ]
                                )
                            else:
                                command_policies = CommandPolicies()

                    target_nodes = self._determine_nodes(
                        *c.args,
                        request_policy=command_policies.request_policy,
                        node_flag=passed_targets,
                    )
                    if not target_nodes:
                        raise RedisClusterException(
                            f"No targets were found to execute {c.args} command on"
                        )
                c.command_policies = command_policies
                if len(target_nodes) > 1:
                    raise RedisClusterException(
                        f"Too many targets for command {c.args}"
                    )

                node = target_nodes[0]
                if node == self._pipe.get_default_node():
                    is_default_node = True

                # now that we know the name of the node
                # ( it's just a string in the form of host:port )
                # we can build a list of commands for each node.
                node_name = node.name
                if node_name not in nodes:
                    redis_node = self._pipe.get_redis_connection(node)
                    try:
                        connection = get_connection(redis_node)
                    except (ConnectionError, TimeoutError):
                        # Release any connections we've already acquired before clearing nodes
                        for n in nodes.values():

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Remove the multi-node target_nodes from the pipeline command and let normal slot routing pick one node: pipe.set('k','v').
  2. If you truly need to broadcast, issue the command through the non-pipeline client: rc.config_rewrite(target_nodes=RedisCluster.ALL_NODES).
  3. If you need the same command on several nodes in a pipeline, queue one entry per node, each with target_nodes=<single ClusterNode>.

Example fix

# before
pipe = rc.pipeline()
pipe.set('k', 'v', target_nodes=RedisCluster.ALL_NODES)  # >1 target
pipe.execute()

# after
rc.set('k', 'v')  # single slot via client
# or, per-node in the pipeline:
for n in rc.get_nodes():
    pipe.set('k', 'v', target_nodes=n)
Defensive patterns

Strategy: validation

Validate before calling

def safe_pipeline_cmd(pipe, method, *args, target=None, **kwargs):
    if target is not None and isinstance(target, (list, tuple, set, dict)) and len(target) > 1:
        raise ValueError('cluster pipeline accepts a single target node per command')
    return getattr(pipe, method)(*args, target_nodes=target, **kwargs)

Type guard

from redis.cluster import ClusterNode

def is_single_node(target) -> bool:
    return target is None or isinstance(target, ClusterNode)

Try / catch

from redis.exceptions import RedisClusterException

try:
    pipe.set('k', 'v', target_nodes=RedisCluster.ALL_NODES)
    pipe.execute()
except RedisClusterException as e:
    if 'Too many targets' in str(e):
        for n in rc.get_nodes():
            pipe.set('k', 'v', target_nodes=n)
        pipe.execute()
    else:
        raise

Prevention

When it happens

Trigger: Passing an explicit multi-node target to a single pipeline command, e.g. pipe.set('k','v', target_nodes=[node_a, node_b]) or pipe.get('k', target_nodes=RedisCluster.ALL_NODES). The resolver fans out to multiple nodes, which the pipeline rejects.

Common situations: Copy-pasting a non-pipeline client call (where multi-node fan-out is supported) into a pipeline. Misunderstanding that cluster pipelines batch per-command-per-node but do not broadcast one command to many nodes. Forgetting that target_nodes=ALL_NODES/PRIMARIES/REPLICAS on a single pipeline command is invalid.

Related errors


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