redis/redis-py · error · RedisClusterException

method multi() is not supported outside of transactional…

Error message

method multi() is not supported outside of transactional context

What it means

ClusterPipeline.multi() is a hard error in the non-transactional PipelineStrategy: cluster pipelines created without transaction=True cannot enter a MULTI block, so calling multi() is treated as a programmer mistake. The transactional strategy (TransactionStrategy) is what actually drives MULTI/EXEC inside execute().

Solutions

  1. Create the pipeline with transaction=True: rc.pipeline(transaction=True) and let execute() wrap the queued commands in MULTI/EXEC automatically.
  2. Do not call multi() explicitly; queue commands directly on the pipeline.
  3. Remove any legacy pipe.multi() call when migrating to the cluster pipeline.

Example fix

// before
pipe = rc.pipeline()
pipe.multi()  # raises
pipe.set('a', 1)
await pipe.execute()

// after
pipe = rc.pipeline(transaction=True)
pipe.set('a', 1)
await pipe.execute()  # MULTI/EXEC handled internally
Defensive patterns

Strategy: validation

Validate before calling

def transactional_pipeline(rc, transaction=True):
    pipe = rc.pipeline(transaction=transaction)
    # do NOT call pipe.multi(); execute() handles MULTI/EXEC
    return pipe

Type guard

null

Try / catch

from redis.exceptions import RedisClusterException
try:
    pipe.multi()
except RedisClusterException as e:
    if 'multi() is not supported' in str(e):
        # recreate as transactional; do not call multi() explicitly
        pipe = rc.pipeline(transaction=True)

Prevention

When it happens

Trigger: Calling pipe.multi() on a pipeline obtained from rc.pipeline() or rc.pipeline(transaction=False). The default cluster pipeline is non-transactional and never supports an explicit multi().

Common situations: Porting standalone-client code that calls pipe.multi() to mark the start of a transaction; misunderstanding that cluster pipelines handle transactions via the transaction=True flag, not an explicit multi() call.

Related errors


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

Appendix: source

Thrown at redis/asyncio/cluster.py:3033

                    # 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 6a6b581b48)