redis/redis-py · error · RedisError

Cannot issue nested calls to MULTI

Error message

Cannot issue nested calls to MULTI

What it means

Raised in `Pipeline.multi()` when `self.explicit_transaction` is already True. `multi()` begins a Redis MULTI/EXEC transactional block; Redis itself forbids nested MULTI, and redis-py enforces this client-side by tracking the explicit_transaction flag. A second call to `multi()` before `execute()`/`discard()` is a programming error.

Source

Thrown at redis/client.py:1889

        self.explicit_transaction = False

        # 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,

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Call `pipe.multi()` exactly once per transaction; end it with `pipe.execute()` or `pipe.discard()`.
  2. If retrying, create a fresh pipeline (`client.pipeline()`) rather than reusing the already-MULTI'd one.
  3. Remove the redundant multi() call — pipeline(transaction=True) already issues MULTI implicitly.

Example fix

# before
pipe = client.pipeline()
pipe.multi()
pipe.multi()  # raises: Cannot issue nested calls to MULTI

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

Strategy: validation

Validate before calling

# Track transaction state in your own wrapper to avoid double-multi
pipe = client.pipeline()
multi_called = False
def begin():
    global multi_called
    if multi_called:
        raise RuntimeError('MULTI already issued')
    pipe.multi(); multi_called = True

Try / catch

from redis.exceptions import RedisError
try:
    pipe.multi()
except RedisError as e:
    if 'nested calls to MULTI' in str(e):
        # already in a transaction — proceed
        pass
    else:
        raise

Prevention

When it happens

Trigger: Calling `pipe.multi()` twice in succession on the same Pipeline without an intervening `execute()` or `discard()`. Also reachable by manually managing transactions and accidentally invoking multi a second time inside a loop or wrapper.

Common situations: Wrapping pipeline in a helper that calls multi() unconditionally; retrying a transaction without resetting the pipeline; copy-paste duplication of the multi() call.

Related errors


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