redis/redis-py · error · RedisClusterException
At least a command with a key is needed to identify a node
Error message
At least a command with a key is needed to identify a node
What it means
Raised in TransactionStrategy._get_client_and_connection_for_transaction (redis/cluster.py:4594) when self._pipeline_slots is empty. A cluster transaction must pin to a single slot's owning node; the slot is learned from the first keyed command. If a transactional operation needs a connection before any keyed command has been queued/watched, the strategy cannot pick a node.
Source
Thrown at redis/cluster.py:4595
self._pipeline_slots: Set[int] = set()
self._transaction_connection: Optional[Connection] = None
self._executing = False
self._retry = copy(self._pipe.retry)
self._retry.update_supported_errors(
RedisCluster.ERRORS_ALLOW_RETRY + self.SLOT_REDIRECT_ERRORS
)
def _get_client_and_connection_for_transaction(self) -> Tuple[Redis, Connection]:
"""
Find a connection for a pipeline transaction.
For running an atomic transaction, watch keys ensure that contents have not been
altered as long as the watch commands for those keys were sent over the same
connection. So once we start watching a key, we fetch a connection to the
node that owns that slot and reuse it.
"""
if not self._pipeline_slots:
raise RedisClusterException(
"At least a command with a key is needed to identify a node"
)
node: ClusterNode = self._nodes_manager.get_node_from_slot(
list(self._pipeline_slots)[0], False
)
redis_node: Redis = self._pipe.get_redis_connection(node)
if self._transaction_connection:
if not redis_node.connection_pool.owns_connection(
self._transaction_connection
):
previous_node = self._nodes_manager.find_connection_owner(
self._transaction_connection
)
previous_node.connection_pool.release(self._transaction_connection)
self._transaction_connection = None
if not self._transaction_connection:View on GitHub (pinned to da03cdc7e8)
Solutions
- Ensure at least one keyed command (GET/SET/HGET/...) is queued or watched before execute().
- Move keyless/admin commands (INFO, CONFIG, CLIENT) out of the transactional pipeline and call them on the client directly with target_nodes.
- If you only needed a MULTI/EXEC wrapper for keyless commands, drop the pipeline and call the client directly.
Example fix
# before
pipe = rc.pipeline(transaction=True)
pipe.multi()
pipe.info() # keyless -> no slot
pipe.execute() # raises: At least a command with a key is needed
# after
rc.info(target_nodes=RedisCluster.PRIMARIES) # admin cmd on client
# or include a keyed command in the transaction:
pipe = rc.pipeline(transaction=True)
pipe.watch('k')
pipe.multi()
pipe.set('k', '1')
pipe.execute() Defensive patterns
Strategy: validation
Validate before calling
def run_transaction(client, keyed_commands, keyless_commands=None):
if not keyed_commands:
raise ValueError('cluster transaction needs at least one keyed command to pin a node')
pipe = client.pipeline(transaction=True)
for args in keyed_commands:
pipe.execute_command(*args)
pipe.execute()
# run keyless commands on the client, not in the transaction
return pipe Try / catch
from redis.exceptions import RedisClusterException
try:
pipe.execute()
except RedisClusterException as e:
if 'command with a key is needed' in str(e):
rc.info(target_nodes=RedisCluster.PRIMARIES) # move keyless cmd out of the txn
else:
raise Prevention
- Ensure at least one keyed command is queued/watched before execute() in a transaction.
- Keep admin/keyless commands out of cluster transactions; call them on the client with target_nodes.
- Validate that your transaction body is non-empty and contains a slottable command.
When it happens
Trigger: Calling pipe.execute() on a transactional pipeline that contains only keyless commands (e.g. pipe.multi(); pipe.info(); pipe.execute()). Or calling an immediate-execute command that needs a connection before any slot has been recorded. WATCH with no key followed by an operation requiring a connection.
Common situations: Building a transaction from admin/keyless commands, which have no slot. Calling MULTI then immediately EXEC with nothing keyed in between. Logic that begins a transaction conditionally and sometimes queues no keyed command.
Related errors
- At least a command with a key is needed to identify a node
- Cannot watch or send commands on different slots
- Cannot identify slot number for command: {args[0]},it cannot
- Cannot issue a WATCH after a MULTI
- All keys involved in a cluster transaction must map to the s
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/9c9d1eb1497eea1d.json.
Report an issue: GitHub.