{"record":{"id":"e19dea2e0e8bda40","repo":"BerriAI/litellm","slug":"cache-key-is-none","errorCode":null,"errorMessage":"cache key is None","messagePattern":"cache key is None","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/caching/caching.py","lineNumber":643,"sourceCode":"                cache_key = self.get_cache_key(**kwargs)\n            if cache_key is not None:\n                if isinstance(result, BaseModel):\n                    result = result.model_dump_json()\n\n                ## DEFAULT TTL ##\n                if self.ttl is not None:\n                    kwargs[\"ttl\"] = self.ttl\n                ## Get Cache-Controls ##\n                _cache_kwargs: Final = kwargs.get(\"cache\", None)\n                if isinstance(_cache_kwargs, dict):\n                    for k, v in _cache_kwargs.items():\n                        if k == \"ttl\":\n                            kwargs[\"ttl\"] = v\n\n                cached_data: Final = {\"timestamp\": time.time(), \"response\": result}\n                return cache_key, cached_data, kwargs\n            else:\n                raise Exception(\"cache key is None\")\n        except Exception as e:\n            raise e\n\n    def add_cache(self, result, **kwargs):\n        \"\"\"\n        Adds a result to the cache.\n\n        Args:\n            *args: args to litellm.completion() or embedding()\n            **kwargs: kwargs to litellm.completion() or embedding()\n\n        Returns:\n            None\n        \"\"\"\n        try:\n            if self.should_use_cache(**kwargs) is not True:\n                return\n            cache_key, cached_data, kwargs = self._add_cache_logic(result=result, **kwargs)","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/caching/caching.py#L625-L661","documentation":"Exception raised in LiteLLM's cache key generation path: after the cache-key computation the code ends up with a None cache key, which makes storing/retrieving the entry meaningless. The surrounding try/except simply re-raises, so the original 'cache key is None' message surfaces to the caller. In practice this indicates the cache-key builder could not derive a key from the given kwargs (e.g. no messages/input, or an unsupported call type).","triggerScenarios":"Calling with caching enabled where the kwargs passed to the cache-key builder lack the data it hashes (no messages for completion, no input for embedding), or a call type/params combination the key builder returns None for. The None check fires on the else branch of the successful-key path.","commonSituations":"Enabling litellm.cache without passing messages; using a custom cache-key function that returns None for some inputs; passing None values in params that defeat key construction.","solutions":["Ensure the minimum inputs for the call type are present (messages for chat, input for embeddings) before the caching layer runs.","If using a custom cache-key function (cache_key builder), make it always return a deterministic string.","As a workaround, pass an explicit cache_key kwarg so LiteLLM skips derivation.","Report the exact kwargs shape upstream if it looks like a valid call failing key derivation."],"exampleFix":"# before\nlitellm.completion(model=\"gpt-4o\", messages=None)  # cache enabled -> cache key is None\n\n# after\nlitellm.completion(model=\"gpt-4o\", messages=[{\"role\": \"user\", \"content\": \"hi\"}])","handlingStrategy":"try-catch","validationCode":"def cache_key_precheck(call_type: str, kwargs: dict) -> None:\n    if call_type in (\"completion\", \"acompletion\") and not kwargs.get(\"messages\"):\n        raise ValueError(\"messages required when caching is enabled\")\n    if call_type in (\"embedding\", \"aembedding\") and not kwargs.get(\"input\"):\n        raise ValueError(\"input required when caching is enabled\")","typeGuard":"def has_cacheable_payload(kwargs: dict) -> bool:\n    return bool(kwargs.get(\"messages\") or kwargs.get(\"input\") or kwargs.get(\"prompt\"))","tryCatchPattern":"try:\n    resp = litellm.completion(model=m, messages=msgs, caching=True)\nexcept Exception as e:\n    if \"cache key is None\" in str(e):\n        logger.error(\"cache key derivation failed; retrying without cache\")\n        resp = litellm.completion(model=m, messages=msgs)\n    else:\n        raise","preventionTips":["Always pass well-formed messages/input when litellm.cache is enabled.","Supply an explicit cache_key kwarg for exotic call shapes.","Wrap cache-enabled calls with a fallback to non-cached execution."],"tags":["caching","cache-key","validation","configuration"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}