{"id":"4d6731ba93fe97c0","repo":"redis/redis-py","slug":"cannot-issue-nested-calls-to-multi-4d6731","errorCode":null,"errorMessage":"Cannot issue nested calls to MULTI","messagePattern":"Cannot issue nested calls to MULTI","errorType":"exception","errorClass":"RedisError","httpStatus":null,"severity":"error","filePath":"redis/client.py","lineNumber":1889,"sourceCode":"        self.explicit_transaction = False\n\n        # we can safely return the connection to the pool here since we're\n        # sure we're no longer WATCHing anything\n        if self.connection:\n            self.connection_pool.release(self.connection)\n            self.connection = None\n\n    def close(self) -> None:\n        \"\"\"Close the pipeline\"\"\"\n        self.reset()\n\n    def multi(self) -> None:\n        \"\"\"\n        Start a transactional block of the pipeline after WATCH commands\n        are issued. End the transactional block with `execute`.\n        \"\"\"\n        if self.explicit_transaction:\n            raise RedisError(\"Cannot issue nested calls to MULTI\")\n        if self.command_stack:\n            raise RedisError(\n                \"Commands without an initial WATCH have already been issued\"\n            )\n        self.explicit_transaction = True\n\n    def execute_command(self, *args, **kwargs):\n        if (self.watching or args[0] == \"WATCH\") and not self.explicit_transaction:\n            return self.immediate_execute_command(*args, **kwargs)\n        return self.pipeline_execute_command(*args, **kwargs)\n\n    def _disconnect_reset_raise_on_watching(\n        self,\n        conn: AbstractConnection,\n        error: Exception,\n        failure_count: Optional[int] = None,\n        start_time: Optional[float] = None,\n        command_name: Optional[str] = None,","sourceCodeStart":1871,"sourceCodeEnd":1907,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/client.py#L1871-L1907","documentation":"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.","triggerScenarios":"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.","commonSituations":"Wrapping pipeline in a helper that calls multi() unconditionally; retrying a transaction without resetting the pipeline; copy-paste duplication of the multi() call.","solutions":["Call `pipe.multi()` exactly once per transaction; end it with `pipe.execute()` or `pipe.discard()`.","If retrying, create a fresh pipeline (`client.pipeline()`) rather than reusing the already-MULTI'd one.","Remove the redundant multi() call — pipeline(transaction=True) already issues MULTI implicitly."],"exampleFix":"# before\npipe = client.pipeline()\npipe.multi()\npipe.multi()  # raises: Cannot issue nested calls to MULTI\n\n# after\npipe = client.pipeline()\npipe.multi()\npipe.set('k', 'v')\npipe.execute()","handlingStrategy":"validation","validationCode":"# Track transaction state in your own wrapper to avoid double-multi\npipe = client.pipeline()\nmulti_called = False\ndef begin():\n    global multi_called\n    if multi_called:\n        raise RuntimeError('MULTI already issued')\n    pipe.multi(); multi_called = True","typeGuard":null,"tryCatchPattern":"from redis.exceptions import RedisError\ntry:\n    pipe.multi()\nexcept RedisError as e:\n    if 'nested calls to MULTI' in str(e):\n        # already in a transaction — proceed\n        pass\n    else:\n        raise","preventionTips":["Call multi() at most once per pipeline.","Create a fresh pipeline for each transaction."],"tags":["pipeline","transaction","multi"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}