BerriAI/litellm · error · ValueError

Redis client does not support Lua script registration

Error message

Redis client does not support Lua script registration

What it means

When LiteLLM registers a Lua script on the async Redis client it tries, in order, client.register_script (standard redis-py) and client.script_load (cluster fallback). If the client object exposes neither method, registration is impossible and raises ValueError. This almost always means the installed redis-py version is too old, a non-redis-py client was injected, or a mock/stub client is being used.

Source

Thrown at litellm/caching/redis_cache.py:668

        if hasattr(_redis_client, "register_script"):
            registered_script: Final = _redis_client.register_script(script)

            async def standalone_executor(keys: Sequence[str], args: Sequence[Any], client: Any = None) -> Any:
                namespaced_keys: Final = tuple(self.check_and_fix_namespace(key=key) for key in keys)
                return await registered_script(keys=namespaced_keys, args=args, client=client)

            return standalone_executor

        if hasattr(_redis_client, "script_load"):
            script_sha: Final = _redis_client.script_load(script)

            async def cluster_executor(keys: Sequence[str], args: Sequence[Any], client: Any = None) -> Any:
                namespaced_keys: Final = tuple(self.check_and_fix_namespace(key=key) for key in keys)
                return await _redis_client.evalsha(script_sha, len(namespaced_keys), *namespaced_keys, *args)

            return cluster_executor

        raise ValueError("Redis client does not support Lua script registration")

    @_redis_circuit_breaker_guard
    async def async_set_cache(self, key, value, **kwargs):
        from redis.asyncio import Redis

        if key is None:
            verbose_logger.debug(
                "LiteLLM Redis Caching: async set() skipped — key is None, value=%r",
                value,
            )
            return None

        start_time: Final = time.time()
        try:
            _redis_client: Final[Redis] = self.init_async_client()
        except Exception as e:
            end_time = time.time()
            _duration = end_time - start_time

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Upgrade redis-py: pip install -U 'redis>=5' (redis.asyncio ships in the same package)
  2. If injecting a custom async client, ensure it exposes register_script (or at minimum script_load)
  3. In tests, use fakeredis.aioredis.FakeRedis which implements register_script

Example fix

# before
pip install 'redis==3.5.3'  # no async register_script

# after
pip install -U 'redis>=5.0'
Defensive patterns

Strategy: validation

Validate before calling

from redis.asyncio import Redis as AsyncRedis

def supports_lua(client) -> bool:
    return hasattr(client, 'register_script') or hasattr(client, 'script_load')

# before wiring RedisCache with a custom client:
assert supports_lua(my_async_client), 'custom redis client must support Lua script registration'

Type guard

def is_lua_capable_redis_client(client: Any) -> TypeGuard[AsyncRedis]:
    return hasattr(client, 'register_script') or hasattr(client, 'script_load')

Prevention

When it happens

Trigger: Using a very old redis-py(<4.x)/redis.asyncio version lacking both APIs; passing a custom client wrapper or mock object into RedisCache that does not expose register_script or script_load; features that run Lua scripts (e.g. distributed locking or atomic cache ops) then trigger _register_script_for_current_loop.

Common situations: Pinning redis<4 in requirements; test suites substituting fakeredis/mocks without script support; exotic managed environments shipping stripped redis clients.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/02ba940a1c22c3cc. Report an issue: GitHub.