redis/redis-py · error · RedisClusterException

method unwatch() is not supported outside of transactional…

Error message

method unwatch() is not supported outside of transactional context

What it means

Raised by AbstractStrategy.unwatch() in redis/cluster.py:4562. UNWATCH clears WATCH markers, but a non-transactional cluster pipeline cannot watch keys in the first place, so unwatch() is meaningless there. Only the TransactionStrategy path handles UNWATCH (it is in IMMEDIATE_EXECUTE_COMMANDS and UNWATCH_COMMANDS).

Solutions

  1. Only call unwatch() within a transactional pipeline after watch() was used.
  2. Remove the unconditional unwatch() call in non-transactional code paths.
  3. Reset the non-transactional pipeline with pipe.reset() if you need to clear state.

Example fix

// before
pipe = rc.pipeline()
try:
    pipe.set('k', 'v')
finally:
    pipe.unwatch()
// after
pipe = rc.pipeline()
try:
    pipe.set('k', 'v')
finally:
    pipe.reset()
Defensive patterns

Strategy: validation

Validate before calling

if getattr(pipe, 'transaction', False) and getattr(pipe, '_watching', False):
    pipe.unwatch()

Type guard

def is_transactional_pipe(pipe) -> bool:
    return bool(getattr(pipe, 'transaction', False))

Try / catch

from redis.exceptions import RedisClusterException
try:
    pipe.unwatch()
except RedisClusterException:
    pass  # nothing to unwatch on non-transactional pipeline

Prevention

When it happens

Trigger: Calling pipe.unwatch() on a ClusterPipeline that was not opened as a transaction, or calling it outside of any watch context.

Common situations: Finally-block cleanup that unconditionally calls unwatch(); standalone pipeline patterns copied to cluster.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/a91fd7d3b3850ce9. Report an issue: GitHub.

Appendix: source

Thrown at redis/cluster.py:4562

        return nodes

    def multi(self):
        raise RedisClusterException(
            "method multi() is not supported outside of transactional context"
        )

    def discard(self):
        raise RedisClusterException(
            "method discard() is not supported outside of transactional context"
        )

    def watch(self, *names):
        raise RedisClusterException(
            "method watch() is not supported outside of transactional context"
        )

    def unwatch(self, *names):
        raise RedisClusterException(
            "method unwatch() is not supported outside of transactional context"
        )

    def delete(self, *names):
        if len(names) != 1:
            raise RedisClusterException(
                "deleting multiple keys is not implemented in pipeline command"
            )

        return self.execute_command("DEL", names[0])

    def unlink(self, *names):
        if len(names) != 1:
            raise RedisClusterException(
                "unlinking multiple keys is not implemented in pipeline command"
            )

        return self.execute_command("UNLINK", names[0])

View on GitHub (pinned to 6a6b581b48)