redis/redis-py · error · RedisError
Cannot issue nested calls to MULTI
Error message
Cannot issue nested calls to MULTI
What it means
Raised by Pipeline.multi() (redis/asyncio/client.py:1895) when self.explicit_transaction is already True. A transactional pipeline is begun with a single multi() call and terminated by execute()/discard(); calling multi() again is a programmer error. The library raises RedisError rather than silently nesting.
Source
Thrown at redis/asyncio/client.py:1895
# the pipeline must not be left holding a reference to a
# connection that is being returned to the pool. Shield the
# release itself so a second cancel cannot split the pool's
# internal in-use/available bookkeeping mid-update.
if self.connection:
connection, self.connection = self.connection, None
await asyncio.shield(self.connection_pool.release(connection))
async def aclose(self) -> None:
"""Alias for reset(), a standard method name for cleanup"""
await self.reset()
def multi(self):
"""
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
) -> Union["Pipeline", Awaitable["Pipeline"]]:
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)
async def _disconnect_reset_raise_on_watching(
self,
conn: Connection,
error: Exception,
failure_count: Optional[int] = None,View on GitHub (pinned to da03cdc7e8)
Solutions
- Call multi() exactly once per transaction; create a fresh pipeline via `client.pipeline(transaction=True)` for each transaction.
- Let `client.pipeline(transaction=True)` auto-issue MULTI so you never call multi() manually.
- Track explicit_transaction state and skip redundant multi() calls.
Example fix
// before pipe = r.pipeline() pipe.multi() pipe.multi() # raises // after pipe = r.pipeline(transaction=True) # MULTI issued automatically on execute; do not call multi()
Defensive patterns
Strategy: validation
Validate before calling
pipe = r.pipeline()
if getattr(pipe, 'explicit_transaction', False):
raise RuntimeError('pipeline already in a transaction')
pipe.multi() Prevention
- Call multi() at most once per pipeline; create a fresh pipeline per transaction.
- Prefer client.pipeline(transaction=True) so MULTI is auto-managed.
- Avoid helper layers that conditionally call multi().
When it happens
Trigger: Calling `pipe.multi()` twice on the same Pipeline object, e.g. in a loop that calls multi() per batch or in a helper that wraps multi() and is invoked twice.
Common situations: Reusing a pipeline across iterations and re-entering multi(); framework code that opens transactions conditionally and double-opens on retry.
Related errors
- Commands without an initial WATCH have already been issued
- Cannot issue a WATCH after a MULTI
- A {type(error).__name__} occurred while watching one or more
- Watched variable changed.
- Wrong number of response items from pipeline execution
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/1777297d646b788b.json.
Report an issue: GitHub.