redis/redis-py · error · RedisError
Cannot issue a WATCH after a MULTI
Error message
Cannot issue a WATCH after a MULTI
What it means
Raised by _validate_watch (as the base RedisError) when WATCH is issued after MULTI has already started an explicit transaction. In Redis, WATCH after MULTI is illegal — keys must be watched before MULTI begins — so the library mirrors that rule on the client side.
Source
Thrown at redis/asyncio/cluster.py:3172
)
self._pipeline_slots.add(slot_number)
elif args[0] not in self.NO_SLOTS_COMMANDS:
raise RedisClusterException(
f"Cannot identify slot number for command: {args[0]},"
"it cannot be triggered in a transaction"
)
return self._immediate_execute_command(*args, **kwargs)
else:
if slot_number is not None:
self._pipeline_slots.add(slot_number)
return super().execute_command(*args, **kwargs)
def _validate_watch(self):
if self._explicit_transaction:
raise RedisError("Cannot issue a WATCH after a MULTI")
self._watching = True
async def _immediate_execute_command(self, *args, **options):
return await self._retry.call_with_retry(
lambda: self._get_connection_and_send_command(*args, **options),
self._reinitialize_on_error,
with_failure_count=True,
)
async def _get_connection_and_send_command(self, *args, **options):
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)
# Start timing for observability
start_time = time.monotonic()View on GitHub (pinned to da03cdc7e8)
Solutions
- Call watch() before multi(): WATCH the keys first, then start the transaction with multi().
- Restructure dynamic pipelines so all WATCH calls are decided and issued before MULTI.
- If you no longer need to watch, call pipe.unwatch() (or reset the pipeline) instead of adding a new WATCH mid-transaction.
Example fix
// before
await pipe.multi()
await pipe.watch('k') # raises [83]
// after
await pipe.watch('k')
await pipe.multi() Defensive patterns
Strategy: validation
Validate before calling
if pipe._explicit_transaction:
raise ValueError('WATCH must be issued before MULTI') Try / catch
from redis.exceptions import RedisError
try:
await pipe.watch('k')
except RedisError as e:
if 'Cannot issue a WATCH after a MULTI' in str(e):
pipe.reset(); await pipe.watch('k') # restart in correct order Prevention
- Always WATCH before MULTI.
- Decide watch keys up front so they aren't added conditionally after MULTI.
When it happens
Trigger: Calling pipe.multi() (which sets _explicit_transaction) and then pipe.watch('k') on a cluster pipeline; any code path that issues WATCH once the explicit MULTI flag is set.
Common situations: Porting standalone-pipeline code that interleaves WATCH and MULTI in the wrong order; building a pipeline dynamically where WATCH is conditionally added after MULTI was already begun.
Related errors
- Cannot issue a WATCH after a MULTI
- Cannot issue a WATCH after a MULTI
- method watch() is not supported outside of transactional con
- At least a command with a key is needed to identify a node
- Cannot watch or send commands on different slots
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/c07556e59b101c81.json.
Report an issue: GitHub.