{"record":{"id":"ad98db08b98985a6","repo":"redis/redis-py","slug":"too-many-targets-for-command-cmd-args","errorCode":null,"errorMessage":"Too many targets for command {cmd.args}","messagePattern":"Too many targets for command (.+?)","errorType":"exception","errorClass":"RedisClusterException","httpStatus":null,"severity":"error","filePath":"redis/asyncio/cluster.py","lineNumber":2945,"sourceCode":"                                request_policy=client._command_flags_mapping[\n                                    command_flag\n                                ]\n                            )\n                        else:\n                            command_policies = CommandPolicies()\n\n                target_nodes = await client._determine_nodes(\n                    *cmd.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 {cmd.args} command on\"\n                    )\n            cmd.command_policies = command_policies\n            if len(target_nodes) > 1:\n                raise RedisClusterException(f\"Too many targets for command {cmd.args}\")\n            node = target_nodes[0]\n            if node.name not in nodes:\n                nodes[node.name] = (node, [])\n            nodes[node.name][1].append(cmd)\n\n        # Start timing for observability\n        start_time = time.monotonic()\n\n        errors = await asyncio.gather(\n            *(\n                asyncio.create_task(node[0].execute_pipeline(node[1]))\n                for node in nodes.values()\n            )\n        )\n\n        # Record operation duration for each node\n        for node_name, (node, commands) in nodes.items():\n            # Find the first error in this node's commands, if any","sourceCodeStart":2927,"sourceCodeEnd":2963,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/asyncio/cluster.py#L2927-L2963","documentation":"Raised in ClusterPipeline._execute() when a queued command resolves to more than one target node. The transactional/non-transactional pipeline strategies send each queued command to exactly one node (cluster pipelines are slot-pinned per command), so a command that would fan out to multiple nodes is rejected because the pipeline cannot represent a multi-node result for one entry.","triggerScenarios":"Queuing a command with an ALL_NODES/PRIMARIES policy or passing target_nodes=[nodeA, nodeB] to a single pipeline entry. Also a multi-key command whose keys do not share a slot when the pipeline is in transaction mode (single-slot constraint).","commonSituations":"Treating a cluster pipeline like the standalone pipeline and expecting fan-out; pipelining cross-slot keys; passing a list of nodes as target_nodes for one queued command.","solutions":["Pin each queued command to a single node: pass target_nodes=<one ClusterNode> or a single node-flag that resolves to one node.","For cross-key bulk writes use mset_nonatomic() which splits per slot, or run separate pipelines per slot.","For commands you genuinely want on every node, execute them directly via execute_command(target_nodes=rc.ALL_NODES) outside the pipeline.","Ensure multi-key pipeline commands share a hash tag so they resolve to one slot."],"exampleFix":"// before\npipe = rc.pipeline()\npipe.execute_command('CONFIG', 'REWRITE', target_nodes=rc.ALL_NODES)  # >1 node\nawait pipe.execute()\n\n// after\nawait rc.execute_command('CONFIG', 'REWRITE', target_nodes=rc.ALL_NODES)\n# or pin the pipeline entry:\npipe = rc.pipeline()\npipe.execute_command('CONFIG', 'REWRITE', target_nodes=rc.get_primaries()[0])\nawait pipe.execute()","handlingStrategy":"type-guard","validationCode":"def single_node_targets(rc, target_nodes):\n    nodes = rc._parse_target_nodes(target_nodes)\n    if len(nodes) > 1:\n        raise ValueError('pipeline commands require exactly one target node')\n    return nodes\n\npipe = rc.pipeline()\npipe.execute_command('CONFIG', 'REWRITE',\n                    target_nodes=rc.get_primaries()[0])","typeGuard":"def is_single_target(rc, t) -> bool:\n    try:\n        return len(rc._parse_target_nodes(t)) == 1\n    except TypeError:\n        return False","tryCatchPattern":"from redis.exceptions import RedisClusterException\ntry:\n    await pipe.execute()\nexcept RedisClusterException as e:\n    if 'Too many targets' in str(e):\n        # move the offending command out of the pipeline and run it directly\n        await rc.execute_command(*cmd.args, target_nodes=rc.ALL_NODES)","preventionTips":["Pin each pipeline command to one node or to keys sharing a hash tag/slot.","Run fan-out commands (ALL_NODES/PRIMARIES) outside the pipeline.","Use mset_nonatomic() for cross-slot bulk writes."],"tags":["cluster","pipeline","routing","cross-slot"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}