redis/redis-py · error · RedisClusterException

method eval() is not implemented

Error message

method eval() is not implemented

What it means

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.

Source

Thrown at redis/cluster.py:4105

    def execute(self, raise_on_error: bool = True) -> List[Any]:
        pass

    @abstractmethod
    def send_cluster_commands(
        self, stack, raise_on_error=True, allow_redirections=True
    ):
        pass

    @abstractmethod
    def reset(self):
        pass

    def exists(self, *keys):
        return self.execute_command("EXISTS", *keys)

    def eval(self):
        """ """
        raise RedisClusterException("method eval() is not implemented")

    def load_scripts(self):
        """ """
        raise RedisClusterException("method load_scripts() is not implemented")

    def script_load_for_pipeline(self, *args, **kwargs):
        """ """
        raise RedisClusterException(
            "method script_load_for_pipeline() is not implemented"
        )

    def annotate_exception(self, exception, number, command):
        """
        Provides extra context to the exception prior to it being handled
        """
        cmd = " ".join(map(safe_str, command))
        msg = (
            f"Command # {number} ({truncate_text(cmd)}) of pipeline "

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. 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.
  2. 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().
  3. For reusable scripts, register them with FUNCTION LOAD and invoke via FCALL/FCALL_RO, which the cluster client routes correctly by key slot.

Example fix

# before
pipe = rc.pipeline()
pipe.eval()  # raises: method eval() is not implemented

# after
rc.eval(script, numkeys, *keys)  # call EVAL on the client, not the pipeline
Defensive patterns

Strategy: validation

Validate before calling

from redis.cluster import RedisCluster

def safe_pipeline_eval(client, script, numkeys, *args):
    if isinstance(client, RedisCluster):
        # cluster pipeline does not implement eval(); call the client directly
        return client.eval(script, numkeys, *args)
    pipe = client.pipeline()
    pipe.eval()
    return pipe

Type guard

from redis.cluster import RedisCluster

def is_cluster_client(client) -> bool:
    return isinstance(client, RedisCluster)

Try / catch

from redis.exceptions import RedisClusterException

try:
    pipe.eval()
except RedisClusterException as e:
    if 'eval() is not implemented' in str(e):
        rc.eval(script, numkeys, *keys)  # fall back to client-side EVAL
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/f098908bfb36b217.json. Report an issue: GitHub.