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 in `Pipeline.watch()` when `self.explicit_transaction` is already True. WATCH must precede MULTI; once a MULTI block has started Redis forbids WATCH until after EXEC/DISCARD. redis-py enforces this client-side by checking the explicit_transaction flag and raising RedisError.

Source

Thrown at redis/client.py:2275

            )
            raise

        finally:
            # in reset() the connection is disconnected before returned to the pool if
            # it is marked for reconnect.
            self.reset()

    def discard(self):
        """
        Flushes all previously queued commands
        See: https://redis.io/commands/DISCARD
        """
        self.execute_command("DISCARD")

    def watch(self, *names):
        """Watches the values at keys ``names``"""
        if self.explicit_transaction:
            raise RedisError("Cannot issue a WATCH after a MULTI")
        return self.execute_command("WATCH", *names)

    def unwatch(self) -> bool:
        """Unwatches all previously specified keys"""
        return self.watching and self.execute_command("UNWATCH") or True

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Issue WATCH before MULTI: `pipe.watch(...); pipe.multi(); ...commands...; pipe.execute()`.
  2. If you need to watch different keys, start a new pipeline and re-do WATCH->MULTI from scratch.
  3. Call `pipe.discard()` to abort the current MULTI, then re-establish WATCH in the correct order on a fresh pipeline.

Example fix

# before
pipe = client.pipeline()
pipe.multi()
pipe.watch('k')  # raises: Cannot issue a WATCH after a MULTI

# after
pipe = client.pipeline()
pipe.watch('k')
pipe.multi()
pipe.set('k', 'v')
pipe.execute()
Defensive patterns

Strategy: validation

Validate before calling

# Enforce correct ordering: WATCH before MULTI
pipe = client.pipeline()
pipe.watch('k')  # always before multi()
pipe.multi()

Try / catch

from redis.exceptions import RedisError
try:
    pipe.watch('k')
except RedisError as e:
    if 'Cannot issue a WATCH after a MULTI' in str(e):
        pipe = client.pipeline(); pipe.watch('k'); pipe.multi()
    else:
        raise

Prevention

When it happens

Trigger: Calling `pipe.multi()` and then `pipe.watch('k')` on the same pipeline. Also reachable by accidentally inverting the order in a helper: multi() then watch() instead of watch() then multi().

Common situations: Misordered transaction setup; refactoring that moved watch() after the multi() call; copy-paste errors.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/6fc0887133e17e86.json. Report an issue: GitHub.