{"record":{"id":"92ddfc6fce316a8b","repo":"redis/redis-py","slug":"commands-without-an-initial-watch-have-already-bee","errorCode":null,"errorMessage":"Commands without an initial WATCH have already been issued","messagePattern":"Commands without an initial WATCH have already been issued","errorType":"exception","errorClass":"RedisError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/client.py","lineNumber":1897,"sourceCode":"            # release itself so a second cancel cannot split the pool's\n            # internal in-use/available bookkeeping mid-update.\n            if self.connection:\n                connection, self.connection = self.connection, None\n                await asyncio.shield(self.connection_pool.release(connection))\n\n    async def aclose(self) -> None:\n        \"\"\"Alias for reset(), a standard method name for cleanup\"\"\"\n        await self.reset()\n\n    def multi(self):\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(\n        self, *args, **kwargs\n    ) -> Union[\"Pipeline\", Awaitable[\"Pipeline\"]]:\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    async def _disconnect_reset_raise_on_watching(\n        self,\n        conn: Connection,\n        error: Exception,\n        failure_count: Optional[int] = None,\n        start_time: Optional[float] = None,\n        command_name: Optional[str] = None,","sourceCodeStart":1879,"sourceCodeEnd":1915,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/asyncio/client.py#L1879-L1915","documentation":"Raised by Pipeline.multi() when command_stack is already non-empty but no WATCH preceded it. The intended workflow is WATCH -> MULTI -> queued commands -> EXEC; issuing commands first (buffered pipeline) and then calling multi() would mix a non-transactional pipeline with a transaction.","triggerScenarios":"Calling pipe.set('a',1); pipe.multi() — i.e. queuing commands before MULTI without a prior WATCH. The library refuses because the queued commands cannot be turned into a transaction retroactively.","commonSituations":"Misunderstanding the pipeline model: assuming multi() can be called after queuing; refactoring that moves multi() below the command calls.","solutions":["Order your calls WATCH (if any) -> multi() -> queued commands -> execute().","If you did not intend a transaction, omit multi() and just call execute() on the buffered pipeline.","Use the context-manager pipeline which enforces the correct order."],"exampleFix":"// before\npipe = client.pipeline(transaction=True)\nawait pipe.set('a', 1)\npipe.multi()\n// after\npipe = client.pipeline(transaction=True)\npipe.multi()\nawait pipe.set('a', 1)\nawait pipe.execute()","handlingStrategy":"validation","validationCode":"assert not pipe.command_stack, 'issue WATCH before any commands, then multi()'\npipe.multi()","typeGuard":"def ready_for_multi(pipe) -> bool:\n    return not pipe.command_stack","tryCatchPattern":"try:\n    pipe.multi()\nexcept RedisError as e:\n    if 'without an initial WATCH' in str(e):\n        # recreate pipeline and issue WATCH -> multi() in order\n        ...","preventionTips":["Always WATCH (if needed) then multi() before queuing commands.","Use the context-manager pipeline to enforce ordering."],"tags":["pipeline","transaction","ordering","multi"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}