{"record":{"id":"f37cf66a0699bab4","repo":"cocoindex-io/cocoindex","slug":"litellm-embedding-response-mixes-items-with-and-wi","errorCode":null,"errorMessage":"litellm embedding response mixes items with and without `index`","messagePattern":"litellm embedding response mixes items with and without `index`","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/ops/litellm.py","lineNumber":189,"sourceCode":"def _aligned_embeddings(data: list[_Any], n: int) -> list[_NDArray[_np.float32]]:\n    \"\"\"Map embedding response items back to the ``n`` inputs they embed.\n\n    Items carrying an ``index`` are placed by it; if no item carries one\n    (missing or ``None``), the response is taken positionally. Mixing the two,\n    or an index set that is not a permutation of ``0..n-1``, raises so a\n    misordered response fails loudly instead of silently misaligning\n    embeddings with their texts.\n    \"\"\"\n    if len(data) != n:\n        raise RuntimeError(\n            f\"litellm embedding response has {len(data)} items for {n} inputs\"\n        )\n    out: list[_NDArray[_np.float32] | None] = [None] * n\n    indexed = n > 0 and data[0].get(\"index\") is not None\n    for pos, item in enumerate(data):\n        index = item.get(\"index\")\n        if (index is not None) != indexed:\n            raise RuntimeError(\n                \"litellm embedding response mixes items with and without `index`\"\n            )\n        if not indexed:\n            index = pos\n        elif type(index) is not int or not 0 <= index < n or out[index] is not None:\n            raise RuntimeError(\n                \"litellm embedding response indices are not a permutation of \"\n                f\"0..{n - 1}: got {[item.get('index') for item in data]}\"\n            )\n        out[index] = _np.array(item[\"embedding\"], dtype=_np.float32)\n    return _cast(list[_NDArray[_np.float32]], out)\n\n\nclass LiteLLMEmbedder(_schema.VectorSchemaProvider):\n    \"\"\"Wrapper for LiteLLM embedding models that implements VectorSchemaProvider.\n\n    This class provides an async interface to LiteLLM's embedding API\n    and automatically provides vector schema information for CocoIndex connectors.","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/ops/litellm.py#L171-L207","documentation":"Raised when a litellm embedding response contains a mix of items with and without an `index` field. The alignment logic decides globally whether the response is index-aligned or positional (based on the first item); a mixture is ambiguous, so the library raises instead of guessing.","triggerScenarios":"The provider returns `data` items where some entries include `\"index\": n` and others omit it or set it to None — e.g. a proxy merging responses from different backends or a partially-migrated API format.","commonSituations":"litellm proxy fanning out a batch to multiple providers; custom gateways rewriting response items; provider SDK upgrades changing whether index is emitted; hand-rolled mock servers used in tests.","solutions":["Log/inspect the raw response to identify which provider or route produces the inconsistent items.","If using a litellm proxy/router, pin the batch to a single provider/deployment so all items share one response format.","Normalize the response before it reaches cocoindex: add `index` to every item (its position) or strip it from all items.","Upgrade litellm if the provider's response format changed recently."],"exampleFix":"// before\ndata = response[\"data\"]  # some items lack \"index\"\n// after\ndata = [{**item, \"index\": i} for i, item in enumerate(response[\"data\"])]","handlingStrategy":"validation","validationCode":"data = resp[\"data\"]\nindexed_flags = {item.get(\"index\") is not None for item in data}\nif len(indexed_flags) > 1:\n    raise ValueError(\"response mixes indexed and positional items\")","typeGuard":null,"tryCatchPattern":"try:\n    embs = embed_op.embed(texts)\nexcept RuntimeError as e:\n    if 'mixes items with and without' in str(e):\n        resp = normalize_indices(raw_response)\n        embs = embed_op.embed(texts)\n    else:\n        raise","preventionTips":["Route a batch to a single provider/deployment through the litellm router.","Normalize proxy responses to one format (all-indexed or all-positional) before feeding the pipeline.","Add a smoke test per provider that asserts a uniform response shape."],"tags":["python","embeddings","litellm","response-shape"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}