redis/redis-py · error · WatchError

A {type(error).__name__} occurred while watching one or more

Error message

A {type(error).__name__} occurred while watching one or more keys

What it means

Raised in `Pipeline._disconnect_reset_raise_on_watching` (the immediate-execution path used for WATCH and pre-MULTI commands). When a retryable connection error occurs while executing a WATCH-time command and retries are exhausted, the connection is disconnected; because the pipeline was in a watching state, the watch is invalidated and a WatchError is raised with the underlying error's type name so the caller knows the transaction must be retried.

Source

Thrown at redis/client.py:1936

        """
        if error and failure_count <= conn.retry.get_retries():
            record_operation_duration(
                command_name=command_name,
                duration_seconds=time.monotonic() - start_time,
                server_address=getattr(conn, "host", None),
                server_port=getattr(conn, "port", None),
                db_namespace=str(conn.db),
                error=error,
                retry_attempts=failure_count,
            )
        conn.disconnect()

        # if we were already watching a variable, the watch is no longer
        # valid since this connection has died. raise a WatchError, which
        # indicates the user should retry this transaction.
        if self.watching:
            self.reset()
            raise WatchError(
                f"A {type(error).__name__} occurred while watching one or more keys"
            )

    def immediate_execute_command(self, *args, **options):
        """
        Execute a command immediately, but don't auto-retry on the supported
        errors for retry if we're already WATCHing a variable.
        Used when issuing WATCH or subsequent commands retrieving their values but before
        MULTI is called.
        """
        command_name = args[0]
        conn = self.connection
        # if this is the first call, we need a connection
        if not conn:
            conn = self.connection_pool.get_connection()
            self.connection = conn

        # Start timing for observability

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Wrap WATCH/EXEC blocks in a retry loop that catches WatchError and re-runs the whole transaction.
  2. Increase `Retry(retries=N)` / tune backoff so transient connection errors are absorbed before the watch is invalidated.
  3. Stabilize the connection to the Redis server (network, timeouts, pool size).
  4. Keep the WATCH->read->MULTI->commands->EXEC window short to minimize exposure to disconnects.

Example fix

# before
with client.pipeline() as pipe:
    try:
        pipe.watch('k')
        v = pipe.get('k')
        pipe.multi()
        pipe.set('k', int(v) + 1)
        pipe.execute()
    except WatchError:
        pass  # silently drops the increment on disconnect

# after
for _ in range(10):
    try:
        with client.pipeline() as pipe:
            pipe.watch('k')
            v = pipe.get('k')
            pipe.multi()
            pipe.set('k', int(v) + 1)
            pipe.execute()
        break
    except WatchError:
        continue
Defensive patterns

Strategy: retry

Try / catch

from redis.exceptions import WatchError
for _ in range(5):
    try:
        with client.pipeline() as pipe:
            pipe.watch('k')
            val = pipe.get('k')
            pipe.multi()
            pipe.set('k', transform(val))
            pipe.execute()
        break
    except WatchError:
        continue  # retry whole transaction

Prevention

When it happens

Trigger: Issuing `pipe.watch('k')` followed by a read (e.g. `pipe.get('k')`) on a flaky connection — the immediate_execute_command path is used. If the connection fails after all retries, `_disconnect_reset_raise_on_watching` resets the pipeline and raises `WatchError: A <ErrorType> occurred while watching one or more keys`.

Common situations: Network partitions or Redis restarts during an optimistic-locking transaction; connection pool churn under load; misconfigured retry/backoff giving up too early.

Related errors


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