{"record":{"id":"e242320060ab9a5f","repo":"redis/redis-py","slug":"deleting-multiple-keys-is-not-implemented-in-pipel","errorCode":null,"errorMessage":"deleting multiple keys is not implemented in pipeline command","messagePattern":"deleting multiple keys is not implemented in pipeline command","errorType":"exception","errorClass":"RedisClusterException","httpStatus":null,"severity":"error","filePath":"redis/cluster.py","lineNumber":4568,"sourceCode":"\n    def discard(self):\n        raise RedisClusterException(\n            \"method discard() is not supported outside of transactional context\"\n        )\n\n    def watch(self, *names):\n        raise RedisClusterException(\n            \"method watch() is not supported outside of transactional context\"\n        )\n\n    def unwatch(self, *names):\n        raise RedisClusterException(\n            \"method unwatch() is not supported outside of transactional context\"\n        )\n\n    def delete(self, *names):\n        if len(names) != 1:\n            raise RedisClusterException(\n                \"deleting multiple keys is not implemented in pipeline command\"\n            )\n\n        return self.execute_command(\"DEL\", names[0])\n\n    def unlink(self, *names):\n        if len(names) != 1:\n            raise RedisClusterException(\n                \"unlinking multiple keys is not implemented in pipeline command\"\n            )\n\n        return self.execute_command(\"UNLINK\", names[0])\n\n\nclass TransactionStrategy(AbstractStrategy):\n    NO_SLOTS_COMMANDS = {\"UNWATCH\"}\n    IMMEDIATE_EXECUTE_COMMANDS = {\"WATCH\", \"UNWATCH\"}\n    UNWATCH_COMMANDS = {\"DISCARD\", \"EXEC\", \"UNWATCH\"}","sourceCodeStart":4550,"sourceCodeEnd":4586,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/cluster.py#L4550-L4586","documentation":"Raised by PipelineStrategy.delete() in redis/cluster.py:4568 when more than one key is passed. DEL of multiple keys in a non-transactional cluster pipeline would require cross-slot routing on a single stacked command, which the pipeline cannot do atomically; the implementation deliberately restricts delete() to a single key.","triggerScenarios":"Calling pipe.delete('k1', 'k2', 'k3') (multiple keys) on a non-transactional ClusterPipeline, especially when keys map to different hash slots.","commonSituations":"Bulk-delete code written for standalone Redis ported to cluster; passing a list/tuple of keys via pipe.delete(*keys).","solutions":["Delete keys one at a time in the pipeline: for k in keys: pipe.delete(k).","Use a transactional pipeline if all keys share a hash tag and you need atomicity.","Use rc.delete(*keys) outside a pipeline for standalone-style multi-key delete (cluster client routes per slot)."],"exampleFix":"// before\nwith rc.pipeline() as pipe:\n    pipe.delete('k1', 'k2', 'k3')\n    pipe.execute()\n// after\nwith rc.pipeline() as pipe:\n    for k in ['k1', 'k2', 'k3']:\n        pipe.delete(k)\n    pipe.execute()","handlingStrategy":"validation","validationCode":"keys = ['k1', 'k2', 'k3']\nwith rc.pipeline() as pipe:\n    for k in keys:\n        pipe.delete(k)\n    pipe.execute()","typeGuard":"def is_single_key(names) -> bool:\n    return len(names) == 1","tryCatchPattern":"from redis.exceptions import RedisClusterException\ntry:\n    pipe.delete(*keys)\nexcept RedisClusterException:\n    for k in keys:\n        pipe.delete(k)","preventionTips":["Never multi-key delete in a non-transactional cluster pipeline.","Loop single-key deletes, or use rc.delete(*keys) outside the pipeline."],"tags":["cluster","pipeline","cross-slot","delete"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}