{"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":2944,"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":2926,"sourceCodeEnd":2962,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/cluster.py#L2926-L2962","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npipe = rc.pipeline()\npipe.flushdb()  # fan-out, resolves to all primaries\npipe.set('k', 'v')\nawait pipe.execute()\n\n// after\npipe = rc.pipeline()\npipe.set('k', 'v')\nawait pipe.execute()\nawait rc.flushdb(target_nodes=RedisCluster.PRIMARIES)","handlingStrategy":"validation","validationCode":"FAN_OUT_COMMANDS = {'FLUSHDB', 'FLUSHALL', 'CONFIG', 'CLIENT', 'CLUSTER', 'BGSAVE', 'BGREWRITEAOF'}\n\ndef split_pipeline_commands(rc, commands):\n    pipe = rc.pipeline()\n    deferred = []\n    for cmd, args in commands:\n        if cmd.upper().split()[0] in FAN_OUT_COMMANDS:\n            deferred.append((cmd, args))\n        else:\n            getattr(pipe, cmd.lower())(*args)\n    return pipe, deferred","typeGuard":"from redis.asyncio.cluster import ClusterNode\n\ndef command_targets_single_node(target_nodes) -> bool:\n    if isinstance(target_nodes, ClusterNode):\n        return True\n    if isinstance(target_nodes, list):\n        return len(target_nodes) <= 1\n    return False  # flag strings like ALL_NODES are multi-target","tryCatchPattern":"from redis.cluster import RedisClusterException\n\npipe = rc.pipeline()\npipe.flushdb()\ntry:\n    await pipe.execute()\nexcept RedisClusterException as e:\n    if 'Too many targets' in str(e):\n        await rc.flushdb(target_nodes=RedisCluster.PRIMARIES)\n    else:\n        raise","preventionTips":["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."],"tags":["redis-cluster","pipeline","multi-target","fan-out"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}