redis/redis-py · error · RedisError

Commands without an initial WATCH have already been issued

Error message

Commands without an initial WATCH have already been issued

What it means

Raised by Pipeline.multi() when self.command_stack is non-empty — meaning commands were already queued before MULTI. In redis-py's transaction model you must call WATCH (and multi()) before queuing any commands; queuing commands first then calling multi() indicates the user meant to use transaction=True implicitly or mis-ordered their calls.

Solutions

  1. Call pipe.multi() BEFORE queuing any commands (after optional WATCH).
  2. Or construct the pipeline with transaction=True and let execute() handle MULTI/EXEC automatically — then you never call multi() yourself.
  3. Reset the pipeline (pipe.reset()) and reorder if you queued commands prematurely.

Example fix

// before
pipe = r.pipeline()
pipe.set('k', 'v')
pipe.multi()  # RedisError

// after (explicit)
pipe = r.pipeline()
pipe.multi()
pipe.set('k', 'v')
pipe.execute()

// after (implicit, preferred)
pipe = r.pipeline(transaction=True)
pipe.set('k', 'v')
pipe.execute()
Defensive patterns

Strategy: validation

Validate before calling

if pipe.command_stack:
    raise RuntimeError('Commands already queued; call multi() before queuing')
pipe.multi()

Type guard

def pipeline_ready_for_multi(pipe) -> bool:
    return not pipe.command_stack and not pipe.explicit_transaction

Try / catch

from redis.exceptions import RedisError
try:
    pipe.multi()
except RedisError as e:
    if 'without an initial WATCH' in str(e):
        pipe.reset()
        pipe.multi()  # retry in correct order
    else:
        raise

Prevention

When it happens

Trigger: Calling pipe.set('k','v') (or any command) before pipe.multi(). The presence of entries in command_stack trips the guard at client.py:1890.

Common situations: Misunderstanding the manual transaction API order (multi must precede command queuing); migrating from pipeline(transaction=True) auto-mode to explicit multi() and getting the order wrong.

Related errors


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

Appendix: source

Thrown at redis/client.py:1891

        # we can safely return the connection to the pool here since we're
        # sure we're no longer WATCHing anything
        if self.connection:
            self.connection_pool.release(self.connection)
            self.connection = None

    def close(self) -> None:
        """Close the pipeline"""
        self.reset()

    def multi(self) -> None:
        """
        Start a transactional block of the pipeline after WATCH commands
        are issued. End the transactional block with `execute`.
        """
        if self.explicit_transaction:
            raise RedisError("Cannot issue nested calls to MULTI")
        if self.command_stack:
            raise RedisError(
                "Commands without an initial WATCH have already been issued"
            )
        self.explicit_transaction = True

    def execute_command(self, *args, **kwargs):
        if (self.watching or args[0] == "WATCH") and not self.explicit_transaction:
            return self.immediate_execute_command(*args, **kwargs)
        return self.pipeline_execute_command(*args, **kwargs)

    def _disconnect_reset_raise_on_watching(
        self,
        conn: AbstractConnection,
        error: Exception,
        failure_count: Optional[int] = None,
        start_time: Optional[float] = None,
        command_name: Optional[str] = None,
    ) -> None:
        """

View on GitHub (pinned to 6a6b581b48)