{"id":"38bdd069a0735e8e","repo":"redis/redis-py","slug":"cannot-watch-or-send-commands-on-different-slots","errorCode":null,"errorMessage":"Cannot watch or send commands on different slots","messagePattern":"Cannot watch or send commands on different slots","errorType":"exception","errorClass":"CrossSlotTransactionError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/cluster.py","lineNumber":3152,"sourceCode":"    async def _execute_command(\n        self, *args: Union[KeyT, EncodableT], **kwargs: Any\n    ) -> Any:\n        if self._pipe.cluster_client._initialize:\n            await self._pipe.cluster_client.initialize()\n\n        slot_number: Optional[int] = None\n        if args[0] not in self.NO_SLOTS_COMMANDS:\n            slot_number = await self._pipe.cluster_client._determine_slot(*args)\n\n        if (\n            self._watching or args[0] in self.IMMEDIATE_EXECUTE_COMMANDS\n        ) and not self._explicit_transaction:\n            if args[0] == \"WATCH\":\n                self._validate_watch()\n\n            if slot_number is not None:\n                if self._pipeline_slots and slot_number not in self._pipeline_slots:\n                    raise CrossSlotTransactionError(\n                        \"Cannot watch or send commands on different slots\"\n                    )\n\n                self._pipeline_slots.add(slot_number)\n            elif args[0] not in self.NO_SLOTS_COMMANDS:\n                raise RedisClusterException(\n                    f\"Cannot identify slot number for command: {args[0]},\"\n                    \"it cannot be triggered in a transaction\"\n                )\n\n            return self._immediate_execute_command(*args, **kwargs)\n        else:\n            if slot_number is not None:\n                self._pipeline_slots.add(slot_number)\n\n            return super().execute_command(*args, **kwargs)\n\n    def _validate_watch(self):","sourceCodeStart":3134,"sourceCodeEnd":3170,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/cluster.py#L3134-L3170","documentation":"Raised as CrossSlotTransactionError inside _execute_command when the pipeline is in WATCH or immediate-execute mode and a newly queued command's slot differs from the slots already accumulated in _pipeline_slots. Redis Cluster transactions are atomic only within one hash slot, so the library refuses to mix slots in a watched/immediate path.","triggerScenarios":"After WATCH('k1') (or after queuing a key command that fixed the transaction's slot), calling another immediate-execute command whose key hashes to a different slot, e.g. WATCH('user:1') then pipeline.get('user:2') where the two keys are not hash-tagged to the same slot.","commonSituations":"Forgetting to use Redis hash tags ({tag}) on keys that must be transacted together; mixing keys with different prefixes in a single WATCH/MULTI block; copying standalone-pipeline code into a cluster pipeline.","solutions":["Ensure every key in the transaction shares a hash tag, e.g. 'user:{1}' and 'account:{1}' so they land in the same slot.","Restructure so all watched + transacted keys belong to one slot; split multi-entity work into per-slot transactions.","If cross-slot atomicity is truly required, move that workflow to a Redis that supports it (single instance, or functional-redis-style multi-key commands like Lua/MULTI on one shard) — not a cluster transaction."],"exampleFix":"// before\nawait pipe.watch('user:1')\nawait pipe.get('user:2')  # different slot -> raises [81]\n// after\nawait pipe.watch('user:{1}')\nawait pipe.get('acct:{1}')  # same slot via hash tag","handlingStrategy":"validation","validationCode":"from redis.cluster import key_slot\nslots = {key_slot(k.encode()) for k in keys_to_watch_or_use}\nif len(slots) > 1:\n    raise ValueError('All keys must share a slot; use hash tags')","typeGuard":null,"tryCatchPattern":"from redis.exceptions import CrossSlotTransactionError\ntry:\n    await pipe.execute()\nexcept CrossSlotTransactionError:\n    # re-bucket keys by hash tag and retry per-slot","preventionTips":["Use {hashtag} on keys that must be transacted together.","Validate slot equality before adding commands to a watched pipeline."],"tags":["cluster","pipeline","transaction","cross-slot","hash-tag"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}