{"id":"f098908bfb36b217","repo":"redis/redis-py","slug":"method-eval-is-not-implemented","errorCode":null,"errorMessage":"method eval() is not implemented","messagePattern":"method eval\\(\\) is not implemented","errorType":"exception","errorClass":"RedisClusterException","httpStatus":null,"severity":"error","filePath":"redis/cluster.py","lineNumber":4105,"sourceCode":"    def execute(self, raise_on_error: bool = True) -> List[Any]:\n        pass\n\n    @abstractmethod\n    def send_cluster_commands(\n        self, stack, raise_on_error=True, allow_redirections=True\n    ):\n        pass\n\n    @abstractmethod\n    def reset(self):\n        pass\n\n    def exists(self, *keys):\n        return self.execute_command(\"EXISTS\", *keys)\n\n    def eval(self):\n        \"\"\" \"\"\"\n        raise RedisClusterException(\"method eval() is not implemented\")\n\n    def load_scripts(self):\n        \"\"\" \"\"\"\n        raise RedisClusterException(\"method load_scripts() is not implemented\")\n\n    def script_load_for_pipeline(self, *args, **kwargs):\n        \"\"\" \"\"\"\n        raise RedisClusterException(\n            \"method script_load_for_pipeline() is not implemented\"\n        )\n\n    def annotate_exception(self, exception, number, command):\n        \"\"\"\n        Provides extra context to the exception prior to it being handled\n        \"\"\"\n        cmd = \" \".join(map(safe_str, command))\n        msg = (\n            f\"Command # {number} ({truncate_text(cmd)}) of pipeline \"","sourceCodeStart":4087,"sourceCodeEnd":4123,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/cluster.py#L4087-L4123","documentation":"ClusterPipeline.eval() delegates to AbstractStrategy.eval() (redis/cluster.py:4103), an intentional stub that always raises RedisClusterException. The cluster pipeline does not implement the standalone pipeline's eval() helper because Lua scripts in cluster mode must be routed per-key-slot, so the plain no-arg helper has no well-defined semantics. Use rc.eval(...) directly on the client, or use registered functions, instead of the pipeline helper.","triggerScenarios":"Calling pipe.eval() on a pipeline obtained from RedisCluster().pipeline(). The call routes ClusterPipeline.eval (redis/cluster.py:3715) -> self._execution_strategy.eval() -> the raising stub at redis/cluster.py:4105. Note the cluster signature takes no arguments, unlike the standalone pipeline.","commonSituations":"Porting code written for redis.Redis().pipeline() that calls pipe.eval(script, numkeys, ...) to RedisCluster. Copy-pasting standalone pipeline patterns into cluster code. Misreading the docs and assuming EVAL works the same way in cluster pipelines.","solutions":["Call EVAL on the RedisCluster client directly, not the pipeline: rc.eval(script, numkeys, *keys_and_args), ensuring all keys map to the same hash slot.","If you need EVAL inside a pipeline-like batch, use a transactional cluster pipeline with keys hashed to the same slot (hash tags) and execute via the client command path, not pipe.eval().","For reusable scripts, register them with FUNCTION LOAD and invoke via FCALL/FCALL_RO, which the cluster client routes correctly by key slot."],"exampleFix":"# before\npipe = rc.pipeline()\npipe.eval()  # raises: method eval() is not implemented\n\n# after\nrc.eval(script, numkeys, *keys)  # call EVAL on the client, not the pipeline","handlingStrategy":"validation","validationCode":"from redis.cluster import RedisCluster\n\ndef safe_pipeline_eval(client, script, numkeys, *args):\n    if isinstance(client, RedisCluster):\n        # cluster pipeline does not implement eval(); call the client directly\n        return client.eval(script, numkeys, *args)\n    pipe = client.pipeline()\n    pipe.eval()\n    return pipe","typeGuard":"from redis.cluster import RedisCluster\n\ndef is_cluster_client(client) -> bool:\n    return isinstance(client, RedisCluster)","tryCatchPattern":"from redis.exceptions import RedisClusterException\n\ntry:\n    pipe.eval()\nexcept RedisClusterException as e:\n    if 'eval() is not implemented' in str(e):\n        rc.eval(script, numkeys, *keys)  # fall back to client-side EVAL\n    else:\n        raise","preventionTips":["Audit pipeline usage for eval/load_scripts/script_load_for_pipeline when migrating to RedisCluster.","Prefer Redis Functions (FCALL) over ad-hoc EVAL in cluster code.","Call scripting commands on the RedisCluster client, never on its pipeline helper."],"tags":["cluster","pipeline","scripting","not-implemented"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}