{"record":{"id":"5e0e0887c024859c","repo":"cocoindex-io/cocoindex","slug":"litellm-embedding-response-indices-are-not-a-permu","errorCode":null,"errorMessage":"litellm embedding response indices are not a permutation of 0..{n - 1}: got {[item.get('index') for item in data]}","messagePattern":"litellm embedding response indices are not a permutation of 0\\.\\.(.+?): got (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/ops/litellm.py","lineNumber":195,"sourceCode":"    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.\n\n    Args:\n        model: LiteLLM model name (e.g., ``\"text-embedding-ada-002\"``,\n            ``\"vertex_ai/textembedding-gecko\"``).\n        **kwargs: Additional keyword arguments passed through to every\n            ``litellm.aembedding`` call (e.g., ``api_key``, ``api_base``,","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/ops/litellm.py#L177-L213","documentation":"Raised when the `index` values in a litellm embedding response are not a valid permutation of 0..n-1 — i.e. an index is not an int, is out of range, or duplicates another index. Positional alignment is impossible in that case, so the library fails loudly rather than placing embeddings at wrong positions.","triggerScenarios":"Provider returns duplicate `index` values, indices >= number of inputs, negative indices, or non-integer indices (e.g. floats or strings) in the embedding response `data` items.","commonSituations":"Proxies or routers that merge/shard batch requests and renumber incorrectly; providers emitting 1-based indices instead of 0-based; index emitted as string due to JSON formatting; sending n inputs but the provider reports indices relative to a different batch.","solutions":["Log the full list of returned indices (included in the error message) to identify the off-by-one or duplication pattern.","If indices are 1-based from the provider, normalize them (subtract 1) or make the request positional by stripping `index` before passing to cocoindex.","Stop sharding the same batch across multiple backend calls, or fix the proxy so indices are unique and 0-based.","Retry with smaller batch sizes to rule out provider-side batch handling bugs."],"exampleFix":"// before\n# provider returns 1-based indices\nresp = embed(texts)  # raises: indices not a permutation of 0..n-1\n// after\nfor item in resp[\"data\"]:\n    item[\"index\"] = int(item[\"index\"]) - 1  # normalize to 0-based","handlingStrategy":"validation","validationCode":"idx = [item.get(\"index\") for item in resp[\"data\"]]\nif sorted(i for i in idx if isinstance(i, int)) != list(range(len(resp[\"data\"]))):\n    raise ValueError(f\"indices not a permutation: {idx}\")","typeGuard":"def is_valid_permutation(indices, n):\n    return len(indices) == n and all(type(i) is int and 0 <= i < n for i in indices) and len(set(indices)) == n","tryCatchPattern":"try:\n    embs = embed_op.embed(texts)\nexcept RuntimeError as e:\n    if 'not a permutation' in str(e):\n        resp = reindex_positionally(raw_response)  # drop provider indices\n        embs = embed_op.embed(texts)\n    else:\n        raise","preventionTips":["Check provider index conventions (0-based vs 1-based) once per integration and normalize.","Avoid splitting one logical batch across multiple backend calls that renumber indices.","Validate indices with a smoke test before wiring a new model route into production."],"tags":["python","embeddings","litellm","index-alignment"],"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"}