redis/redis-py · error · TypeError
target_nodes type can be one of the following: node_flag…
Error message
target_nodes type can be one of the following: node_flag (PRIMARIES, REPLICAS, RANDOM, ALL_NODES),ClusterNode, list<ClusterNode>, or dict<any, ClusterNode>. The passed type is {type(target_nodes)} What it means
Raised as a TypeError by _parse_target_nodes() when the target_nodes argument is not one of the accepted types: a node_flag string (PRIMARIES, REPLICAS, RANDOM, ALL_NODES), a ClusterNode instance, a list of ClusterNode, or a dict mapping names to ClusterNode. The guard at cluster.py:1527-1532 checks isinstance for each valid type and raises for anything else, including the type in the message.
Solutions
- Use the node_flag string constants: 'PRIMARIES', 'REPLICAS', 'ALL_NODES', or 'RANDOM'.
- Pass a ClusterNode obtained from client.get_node(host, port) or client.get_primaries().
- Pass a list of ClusterNode objects or a dict of {name: ClusterNode}.
Example fix
// before
client.execute_command('INFO', target_nodes='primary')
// after
client.execute_command('INFO', target_nodes='PRIMARIES') Defensive patterns
Strategy: type-guard
Validate before calling
from redis.cluster import ClusterNode
valid_flags = {'PRIMARIES', 'REPLICAS', 'ALL_NODES', 'RANDOM'}
def validate_target_nodes(tn):
if isinstance(tn, str) and tn not in valid_flags:
raise TypeError(f'Invalid node_flag: {tn}. Use one of {valid_flags}')
if not isinstance(tn, (str, ClusterNode, list, dict)):
raise TypeError(f'Invalid target_nodes type: {type(tn)}')
return tn Type guard
from redis.cluster import ClusterNode
VALID_FLAGS = {'PRIMARIES', 'REPLICAS', 'ALL_NODES', 'RANDOM'}
def is_valid_target_nodes(tn) -> bool:
if isinstance(tn, str):
return tn in VALID_FLAGS
if isinstance(tn, ClusterNode):
return True
if isinstance(tn, list):
return all(isinstance(n, ClusterNode) for n in tn)
if isinstance(tn, dict):
return all(isinstance(v, ClusterNode) for v in tn.values())
return False Try / catch
null
Prevention
- Use the node_flag string constants exactly: PRIMARIES, REPLICAS, ALL_NODES, RANDOM.
- Pass ClusterNode objects obtained from client.get_node() or get_primaries().
- Never pass host:port strings or integers as target_nodes.
When it happens
Trigger: Passing target_nodes as a string that isn't a node_flag, an integer, a tuple, or any object that isn't ClusterNode or a container of ClusterNode, e.g. client.get('key', target_nodes=123) or target_nodes=' primaries' (typo).
Common situations: Passing the host:port string instead of a ClusterNode object, passing a single host string, or a typo in the node_flag constant name.
Related errors
- No way to dispatch this command to Redis Cluster. Missing…
- Argument 'db' must be 0 or None in cluster mode
- Cache must implement CacheInterface
- Cannot disable maintenance notifications after enabling them
- Cannot enable maintenance notifications for connection…
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/2ea1b368971f80ae.
Report an issue: GitHub.
Appendix: source
Thrown at redis/cluster.py:1527
"""
return self.nodes_manager.connection_kwargs
def _is_nodes_flag(self, target_nodes):
return isinstance(target_nodes, str) and target_nodes in self.node_flags
def _parse_target_nodes(self, target_nodes):
if isinstance(target_nodes, list):
nodes = target_nodes
elif isinstance(target_nodes, ClusterNode):
# Supports passing a single ClusterNode as a variable
nodes = [target_nodes]
elif isinstance(target_nodes, dict):
# Supports dictionaries of the format {node_name: node}.
# It enables to execute commands with multi nodes as follows:
# rc.cluster_save_config(rc.get_primaries())
nodes = target_nodes.values()
else:
raise TypeError(
"target_nodes type can be one of the following: "
"node_flag (PRIMARIES, REPLICAS, RANDOM, ALL_NODES),"
"ClusterNode, list<ClusterNode>, or dict<any, ClusterNode>. "
f"The passed type is {type(target_nodes)}"
)
return nodes
def execute_command(self, *args, **kwargs):
return self._internal_execute_command(*args, **kwargs)
def _internal_execute_command(self, *args, **kwargs):
"""
Wrapper for ERRORS_ALLOW_RETRY error handling.
It will try the number of times specified by the retries property from
config option "self.retry" which defaults to 10 unless manually
configured.
View on GitHub (pinned to 6a6b581b48)