{"id":"a62e762a450c6b19","repo":"redis/redis-py","slug":"too-many-targets-for-command-c-args","errorCode":null,"errorMessage":"Too many targets for command {c.args}","messagePattern":"Too many targets for command (.+?)","errorType":"exception","errorClass":"RedisClusterException","httpStatus":null,"severity":"error","filePath":"redis/cluster.py","lineNumber":4296,"sourceCode":"                                    request_policy=self._pipe._command_flags_mapping[\n                                        command_flag\n                                    ]\n                                )\n                            else:\n                                command_policies = CommandPolicies()\n\n                    target_nodes = self._determine_nodes(\n                        *c.args,\n                        request_policy=command_policies.request_policy,\n                        node_flag=passed_targets,\n                    )\n                    if not target_nodes:\n                        raise RedisClusterException(\n                            f\"No targets were found to execute {c.args} command on\"\n                        )\n                c.command_policies = command_policies\n                if len(target_nodes) > 1:\n                    raise RedisClusterException(\n                        f\"Too many targets for command {c.args}\"\n                    )\n\n                node = target_nodes[0]\n                if node == self._pipe.get_default_node():\n                    is_default_node = True\n\n                # now that we know the name of the node\n                # ( it's just a string in the form of host:port )\n                # we can build a list of commands for each node.\n                node_name = node.name\n                if node_name not in nodes:\n                    redis_node = self._pipe.get_redis_connection(node)\n                    try:\n                        connection = get_connection(redis_node)\n                    except (ConnectionError, TimeoutError):\n                        # Release any connections we've already acquired before clearing nodes\n                        for n in nodes.values():","sourceCodeStart":4278,"sourceCodeEnd":4314,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/cluster.py#L4278-L4314","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove the multi-node target_nodes from the pipeline command and let normal slot routing pick one node: pipe.set('k','v').","If you truly need to broadcast, issue the command through the non-pipeline client: rc.config_rewrite(target_nodes=RedisCluster.ALL_NODES).","If you need the same command on several nodes in a pipeline, queue one entry per node, each with target_nodes=<single ClusterNode>."],"exampleFix":"# before\npipe = rc.pipeline()\npipe.set('k', 'v', target_nodes=RedisCluster.ALL_NODES)  # >1 target\npipe.execute()\n\n# after\nrc.set('k', 'v')  # single slot via client\n# or, per-node in the pipeline:\nfor n in rc.get_nodes():\n    pipe.set('k', 'v', target_nodes=n)","handlingStrategy":"validation","validationCode":"def safe_pipeline_cmd(pipe, method, *args, target=None, **kwargs):\n    if target is not None and isinstance(target, (list, tuple, set, dict)) and len(target) > 1:\n        raise ValueError('cluster pipeline accepts a single target node per command')\n    return getattr(pipe, method)(*args, target_nodes=target, **kwargs)","typeGuard":"from redis.cluster import ClusterNode\n\ndef is_single_node(target) -> bool:\n    return target is None or isinstance(target, ClusterNode)","tryCatchPattern":"from redis.exceptions import RedisClusterException\n\ntry:\n    pipe.set('k', 'v', target_nodes=RedisCluster.ALL_NODES)\n    pipe.execute()\nexcept RedisClusterException as e:\n    if 'Too many targets' in str(e):\n        for n in rc.get_nodes():\n            pipe.set('k', 'v', target_nodes=n)\n        pipe.execute()\n    else:\n        raise","preventionTips":["Never pass multi-node flags (ALL_NODES/PRIMARIES/REPLICAS) to a single pipeline command.","Queue one command per node if you must broadcast inside a pipeline.","Reserve multi-node fan-out for the non-pipeline client API."],"tags":["cluster","pipeline","routing","api-misuse"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}