redis/redis-py · error · RedisClusterException
method multi() is not supported outside of transactional con
Error message
method multi() is not supported outside of transactional context
What it means
Raised unconditionally by PipelineStrategy.multi() — the non-transactional cluster pipeline strategy. In cluster mode a transactional pipeline is selected by passing transaction=True to rc.pipeline(); without it, the pipeline is fire-and-forget across shards and has no MULTI/EXEC context, so calling multi() on it is meaningless and is rejected.
Source
Thrown at redis/asyncio/cluster.py:3032
# Note: when the error is raised we'll reset the default node in the
# caller function.
for cmd in default_node[1]:
# Check if it has a command that failed with a relevant
# exception
if type(cmd.result) in RedisCluster.ERRORS_ALLOW_RETRY:
client.replace_default_node()
break
return [cmd.result for cmd in stack]
async def reset(self):
"""
Reset back to empty pipeline.
"""
self._command_queue = []
def multi(self):
raise RedisClusterException(
"method multi() is not supported outside of transactional context"
)
async def watch(self, *names):
raise RedisClusterException(
"method watch() is not supported outside of transactional context"
)
async def unwatch(self):
raise RedisClusterException(
"method unwatch() is not supported outside of transactional context"
)
async def discard(self):
raise RedisClusterException(
"method discard() is not supported outside of transactional context"
)
View on GitHub (pinned to da03cdc7e8)
Solutions
- Create the pipeline as transactional: pipe = rc.pipeline(transaction=True), then call pipe.multi() if needed.
- If you don't need a transaction, drop the multi() call — the non-transactional pipeline executes queued commands directly.
- Use rc.pipeline(transaction=True) and let the strategy manage MULTI/EXEC automatically rather than calling multi() yourself.
Example fix
// before pipe = rc.pipeline() pipe.multi() # raises // after pipe = rc.pipeline(transaction=True) pipe.multi()
Defensive patterns
Strategy: validation
Validate before calling
def transactional_pipeline(rc, transaction=True):
pipe = rc.pipeline(transaction=transaction)
if transaction:
pipe.multi() # only valid on the transactional strategy
return pipe Type guard
from redis.asyncio.cluster import PipelineStrategy, TransactionStrategy
def supports_multi(pipe) -> bool:
return isinstance(pipe._strategy, TransactionStrategy) Try / catch
from redis.cluster import RedisClusterException
try:
pipe.multi()
except RedisClusterException as e:
if 'multi()' in str(e):
pipe = rc.pipeline(transaction=True)
pipe.multi()
else:
raise Prevention
- Create the pipeline with transaction=True whenever you intend to call multi().
- Centralize pipeline creation so transaction mode is set consistently.
- Don't call multi() manually — let the transactional strategy manage it.
When it happens
Trigger: Calling pipe.multi() on a pipeline created via rc.pipeline() or rc.pipeline(transaction=False). Only the TransactionStrategy (rc.pipeline(transaction=True)) supports multi(); the default PipelineStrategy raises immediately.
Common situations: Porting standalone Redis pipeline code (where multi() is used to start a transaction) to cluster mode without transaction=True; calling multi() twice; mixing the two pipeline flavors.
Related errors
- method watch() is not supported outside of transactional con
- method unwatch() is not supported outside of transactional c
- method discard() is not supported outside of transactional c
- Cannot issue nested calls to MULTI
- shard_hint is deprecated in cluster mode
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/5f8f4e6c76a6c5f4.json.
Report an issue: GitHub.