{"record":{"id":"1eb5153f7e148967","repo":"BerriAI/litellm","slug":"missing-expected-key-in-embedding-response-e","errorCode":null,"errorMessage":"Missing expected key in embedding response: {e}","messagePattern":"Missing expected key in embedding response: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/caching/caching.py","lineNumber":726,"sourceCode":"                    \"embedding\": data.get(\"embedding\"),\n                    \"index\": data.get(\"index\"),\n                    \"object\": data.get(\"object\"),\n                    \"model\": model,\n                    \"prompt_tokens\": prompt_tokens,\n                    \"prompt_tokens_details\": prompt_tokens_details,\n                }\n            else:\n                data = vars(embedding_response)\n                return {\n                    \"embedding\": data.get(\"embedding\"),\n                    \"index\": data.get(\"index\"),\n                    \"object\": data.get(\"object\"),\n                    \"model\": model,\n                    \"prompt_tokens\": prompt_tokens,\n                    \"prompt_tokens_details\": prompt_tokens_details,\n                }\n        except KeyError as e:\n            raise ValueError(f\"Missing expected key in embedding response: {e}\")\n\n    def _get_per_item_prompt_tokens_details(\n        self,\n        result: EmbeddingResponse,\n        idx_in_result_data: int,\n    ) -> dict | None:\n        \"\"\"\n        Extract per-item prompt_tokens_details from a response for caching.\n\n        For single-item responses (common for multimodal providers like Bedrock Titan,\n        Nova, Vertex AI), returns the full prompt_tokens_details.\n        For multi-item responses, distributes integer fields evenly across items\n        so that summing all per-item details reconstructs the original totals.\n        \"\"\"\n        if result.usage is None or result.usage.prompt_tokens_details is None:\n            return None\n\n        details: Final = result.usage.prompt_tokens_details","sourceCodeStart":708,"sourceCodeEnd":744,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/caching/caching.py#L708-L744","documentation":"ValueError raised while LiteLLM converts an embedding response into the cacheable per-item dict form: a KeyError occurred while accessing expected attributes/keys of the response data. The f-string interpolates the missing key name (the KeyError), telling you exactly which field was absent. It signals a provider response shape that does not match what the caching layer expects for embeddings.","triggerScenarios":"Using response caching with embeddings where the provider's EmbeddingResponse data items lack standard keys (e.g. no 'embedding' or 'index'), so the dict/vars-based extraction in the caching helper raises KeyError, which is caught and re-raised as this ValueError.","commonSituations":"A new or non-standard embedding provider whose transformation returns incomplete data objects; a LiteLLM version where a provider transformation was updated but the caching extraction was not; multimodal providers with atypical per-item structure.","solutions":["Check the interpolated key name in the message to see which field is missing from the embedding response data.","Upgrade LiteLLM — provider transformation/cache extraction mismatches are usually fixed in patch releases.","As a workaround, disable caching for that embedding model (or route around the cache) until compatible.","File an upstream issue with the provider name and response sample."],"exampleFix":"# before\nlitellm.cache = litellm.Cache(type=\"redis\")\nlitellm.embedding(model=\"provider/embed-model\", input=[\"hi\"])  # -> ValueError: Missing expected key\n\n# after (temporarily bypass cache for that model)\nlitellm.embedding(model=\"provider/embed-model\", input=[\"hi\"], cache={\"no-cache\": True})","handlingStrategy":"fallback","validationCode":"def embedding_response_is_well_formed(resp) -> bool:\n    try:\n        return all(d.get(\"embedding\") is not None and d.get(\"index\") is not None for d in resp.data)\n    except (AttributeError, KeyError):\n        return False","typeGuard":"def is_cacheable_embedding_response(resp) -> bool:\n    return hasattr(resp, \"data\") and all(isinstance(d, dict) or hasattr(d, \"embedding\") for d in getattr(resp, \"data\", []))","tryCatchPattern":"try:\n    resp = litellm.embedding(model=embed_model, input=inp)  # cache enabled\nexcept ValueError as e:\n    if \"Missing expected key in embedding response\" in str(e):\n        with cache_disabled():\n            resp = litellm.embedding(model=embed_model, input=inp)\n    else:\n        raise","preventionTips":["Keep LiteLLM updated when adding new embedding providers.","Smoke-test each embedding provider with caching enabled in staging before rollout.","Maintain a per-model cache toggle so one bad provider doesn't break all embedding traffic."],"tags":["caching","embeddings","provider-compat","schema-drift"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}