redis/redis-py · error · RedisClusterException

No targets were found to execute

Error message

No targets were found to execute {args} command on

What it means

Raised as a RedisClusterException by _internal_execute_command() when _determine_nodes() returns an empty list, meaning the routing logic found no nodes to send the command to. This happens when the command's request policy resolves to a node group that is empty in the current topology (e.g., command routed to REPLICAS but no replicas exist, or to a specific slot that has no serving node). The guard is at cluster.py:1622-1625.

Solutions

  1. Verify the cluster has nodes of the required type (e.g., run CLUSTER NODES to confirm replicas exist if routing to REPLICAS).
  2. Pass an explicit target_nodes that is guaranteed non-empty, e.g. target_nodes='PRIMARIES' or a specific ClusterNode.
  3. Retry after a topology refresh completes if the error is transient.

Example fix

// before
client.execute_command('GET', 'key', target_nodes='REPLICAS')  # no replicas exist

// after
client.execute_command('GET', 'key', target_nodes='PRIMARIES')
Defensive patterns

Strategy: try-catch

Validate before calling

# Verify the target node group is non-empty before executing
if not client.get_primaries():
    raise RuntimeError('No primary nodes available in the cluster')

Type guard

def has_available_nodes(client, group='PRIMARIES') -> bool:
    if group == 'PRIMARIES':
        return len(client.get_primaries()) > 0
    if group == 'REPLICAS':
        return len(client.get_replicas()) > 0
    return len(client.get_nodes()) > 0

Try / catch

from redis.exceptions import RedisClusterException
try:
    result = client.execute_command('GET', 'key', target_nodes='REPLICAS')
except RedisClusterException as e:
    if 'No targets were found' in str(e):
        result = client.execute_command('GET', 'key', target_nodes='PRIMARIES')

Prevention

When it happens

Trigger: Running a command whose policy targets replicas (target_nodes='REPLICAS' or a command with a replica request policy) in a cluster with no replica nodes, or running a command when all candidate nodes have been removed from the node cache during topology refresh.

Common situations: A cluster configured with no replicas where read_from_replicas routes to the replica group, or a topology refresh that just ran and temporarily cleared node groups, or a command flag misconfiguration.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/870237e8a6794650. Report an issue: GitHub.

Appendix: source

Thrown at redis/cluster.py:1623

        execute_attempts = 1 + retry_attempts
        failure_count = 0

        # Start timing for observability
        start_time = time.monotonic()

        for _ in range(execute_attempts):
            try:
                res = {}
                if not target_nodes_specified:
                    # Determine the nodes to execute the command on
                    target_nodes = self._determine_nodes(
                        *args,
                        request_policy=command_policies.request_policy,
                        nodes_flag=passed_targets,
                    )

                    if not target_nodes:
                        raise RedisClusterException(
                            f"No targets were found to execute {args} command on"
                        )
                    if (
                        len(target_nodes) == 1
                        and target_nodes[0] == self.get_default_node()
                    ):
                        is_default_node = True
                for node in target_nodes:
                    res[node.name] = self._execute_command(node, *args, **kwargs)

                    if command_policies.response_policy == ResponsePolicy.ONE_SUCCEEDED:
                        break

                # Return the processed result
                return self._process_result(
                    args[0],
                    res,
                    response_policy=command_policies.response_policy,

View on GitHub (pinned to 6a6b581b48)