{"record":{"id":"02ba940a1c22c3cc","repo":"BerriAI/litellm","slug":"redis-client-does-not-support-lua-script-registrat","errorCode":null,"errorMessage":"Redis client does not support Lua script registration","messagePattern":"Redis client does not support Lua script registration","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/caching/redis_cache.py","lineNumber":668,"sourceCode":"        if hasattr(_redis_client, \"register_script\"):\n            registered_script: Final = _redis_client.register_script(script)\n\n            async def standalone_executor(keys: Sequence[str], args: Sequence[Any], client: Any = None) -> Any:\n                namespaced_keys: Final = tuple(self.check_and_fix_namespace(key=key) for key in keys)\n                return await registered_script(keys=namespaced_keys, args=args, client=client)\n\n            return standalone_executor\n\n        if hasattr(_redis_client, \"script_load\"):\n            script_sha: Final = _redis_client.script_load(script)\n\n            async def cluster_executor(keys: Sequence[str], args: Sequence[Any], client: Any = None) -> Any:\n                namespaced_keys: Final = tuple(self.check_and_fix_namespace(key=key) for key in keys)\n                return await _redis_client.evalsha(script_sha, len(namespaced_keys), *namespaced_keys, *args)\n\n            return cluster_executor\n\n        raise ValueError(\"Redis client does not support Lua script registration\")\n\n    @_redis_circuit_breaker_guard\n    async def async_set_cache(self, key, value, **kwargs):\n        from redis.asyncio import Redis\n\n        if key is None:\n            verbose_logger.debug(\n                \"LiteLLM Redis Caching: async set() skipped — key is None, value=%r\",\n                value,\n            )\n            return None\n\n        start_time: Final = time.time()\n        try:\n            _redis_client: Final[Redis] = self.init_async_client()\n        except Exception as e:\n            end_time = time.time()\n            _duration = end_time - start_time","sourceCodeStart":650,"sourceCodeEnd":686,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/caching/redis_cache.py#L650-L686","documentation":"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.","triggerScenarios":"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.","commonSituations":"Pinning redis<4 in requirements; test suites substituting fakeredis/mocks without script support; exotic managed environments shipping stripped redis clients.","solutions":["Upgrade redis-py: pip install -U 'redis>=5' (redis.asyncio ships in the same package)","If injecting a custom async client, ensure it exposes register_script (or at minimum script_load)","In tests, use fakeredis.aioredis.FakeRedis which implements register_script"],"exampleFix":"# before\npip install 'redis==3.5.3'  # no async register_script\n\n# after\npip install -U 'redis>=5.0'","handlingStrategy":"validation","validationCode":"from redis.asyncio import Redis as AsyncRedis\n\ndef supports_lua(client) -> bool:\n    return hasattr(client, 'register_script') or hasattr(client, 'script_load')\n\n# before wiring RedisCache with a custom client:\nassert supports_lua(my_async_client), 'custom redis client must support Lua script registration'","typeGuard":"def is_lua_capable_redis_client(client: Any) -> TypeGuard[AsyncRedis]:\n    return hasattr(client, 'register_script') or hasattr(client, 'script_load')","tryCatchPattern":null,"preventionTips":["Pin redis>=5 in requirements","Run a startup smoke test that writes and reads through the cache","Use fakeredis.aioredis.FakeRedis in tests — it implements register_script"],"tags":["redis","lua","dependency","version","initialization"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}