redis/redis-py · error · CrossSlotTransactionError
All keys involved in a cluster transaction must map to the…
Error message
All keys involved in a cluster transaction must map to the same slot
What it means
CrossSlotTransactionError raised at the top of TransactionStrategy._execute_transaction (redis/asyncio/cluster.py:3377) when the accumulated pipeline slots contain more than one distinct slot. Redis Cluster guarantees atomicity only within a single slot, so a MULTI/EXEC block spanning multiple slots is impossible. This fires at execute() time after all commands were queued.
Solutions
- Group keys by hash slot using hash tags, e.g. 'k{group1}', so all keys share a slot
- Split into several single-slot transactions
- If atomicity is not required, use the non-atomic cluster pipeline strategy
Example fix
// before
pipe.multi()
pipe.set('user:1', 'a')
pipe.set('account:2', 'b')
await pipe.execute()
// after - same slot via shared hash tag
pipe.multi()
pipe.set('user:{group1}', 'a')
pipe.set('account:{group1}', 'b')
await pipe.execute() Defensive patterns
Strategy: validation
Validate before calling
from redis.cluster import key_slot
slots = {key_slot(k.encode()) for k in keys}
if len(slots) > 1:
raise ValueError('transaction keys span multiple slots; use hash tags or split') Try / catch
try:
await pipe.execute()
except CrossSlotTransactionError:
# rebucket with hash tags or split into per-slot transactions Prevention
- Use hash tags to colocate transaction keys
- Validate slots before calling execute()
When it happens
Trigger: Queueing `pipe.set('k1', '1'); pipe.set('k2', '2'); await pipe.execute()` inside a transaction where k1 and k2 map to different slots.
Common situations: Porting a standalone-Redis transactional pipeline to cluster without hash tags; aggregating unrelated keys in one transaction.
Related errors
- At least a command with a key is needed to identify a node
- Cannot identify slot number for command
- Cannot issue a WATCH after a MULTI
- Cannot watch or send commands on different slots
- Cannot watch or send commands on different slots
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/9cefd59b7f148014.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/cluster.py:3378
return await self._execute_transaction_with_retries(stack, raise_on_error)
async def _execute_transaction_with_retries(
self, stack: List["PipelineCommand"], raise_on_error: bool
):
return await self._retry.call_with_retry(
lambda: self._execute_transaction(stack, raise_on_error),
lambda error, failure_count: self._reinitialize_on_error(
error, failure_count
),
with_failure_count=True,
)
async def _execute_transaction(
self, stack: List["PipelineCommand"], raise_on_error: bool
):
if len(self._pipeline_slots) > 1:
raise CrossSlotTransactionError(
"All keys involved in a cluster transaction must map to the same slot"
)
self._executing = True
redis_node, connection = self._get_client_and_connection_for_transaction()
# Only disconnect if not watching - disconnecting would lose WATCH state
if not self._watching:
await redis_node.disconnect_if_needed(connection)
# Ensure fieldsets referenced by buffered HIMPORT SETs are prepared on this
# node's connection before the MULTI/EXEC block (session state, not
# transactional). All keys share one slot here, so it is a single node.
await redis_node._himport_prepare_pipeline(connection, stack)
stack = chain(
[PipelineCommand(0, "MULTI")],
stack,View on GitHub (pinned to 6a6b581b48)