{"id":"5f8f4e6c76a6c5f4","repo":"redis/redis-py","slug":"method-multi-is-not-supported-outside-of-transac","errorCode":null,"errorMessage":"method multi() is not supported outside of transactional context","messagePattern":"method multi\\(\\) is not supported outside of transactional context","errorType":"exception","errorClass":"RedisClusterException","httpStatus":null,"severity":"error","filePath":"redis/asyncio/cluster.py","lineNumber":3032,"sourceCode":"                    # Note: when the error is raised we'll reset the default node in the\n                    # caller function.\n                    for cmd in default_node[1]:\n                        # Check if it has a command that failed with a relevant\n                        # exception\n                        if type(cmd.result) in RedisCluster.ERRORS_ALLOW_RETRY:\n                            client.replace_default_node()\n                            break\n\n        return [cmd.result for cmd in stack]\n\n    async def reset(self):\n        \"\"\"\n        Reset back to empty pipeline.\n        \"\"\"\n        self._command_queue = []\n\n    def multi(self):\n        raise RedisClusterException(\n            \"method multi() is not supported outside of transactional context\"\n        )\n\n    async def watch(self, *names):\n        raise RedisClusterException(\n            \"method watch() is not supported outside of transactional context\"\n        )\n\n    async def unwatch(self):\n        raise RedisClusterException(\n            \"method unwatch() is not supported outside of transactional context\"\n        )\n\n    async def discard(self):\n        raise RedisClusterException(\n            \"method discard() is not supported outside of transactional context\"\n        )\n","sourceCodeStart":3014,"sourceCodeEnd":3050,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/cluster.py#L3014-L3050","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npipe = rc.pipeline()\npipe.multi()  # raises\n\n// after\npipe = rc.pipeline(transaction=True)\npipe.multi()","handlingStrategy":"validation","validationCode":"def transactional_pipeline(rc, transaction=True):\n    pipe = rc.pipeline(transaction=transaction)\n    if transaction:\n        pipe.multi()  # only valid on the transactional strategy\n    return pipe","typeGuard":"from redis.asyncio.cluster import PipelineStrategy, TransactionStrategy\n\ndef supports_multi(pipe) -> bool:\n    return isinstance(pipe._strategy, TransactionStrategy)","tryCatchPattern":"from redis.cluster import RedisClusterException\n\ntry:\n    pipe.multi()\nexcept RedisClusterException as e:\n    if 'multi()' in str(e):\n        pipe = rc.pipeline(transaction=True)\n        pipe.multi()\n    else:\n        raise","preventionTips":["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."],"tags":["redis-cluster","pipeline","transaction","multi"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}