{"record":{"id":"e34cea8f09cc385f","repo":"tirth8205/code-review-graph","slug":"openai-api-returned-malformed-indices-got-indice","errorCode":null,"errorMessage":"OpenAI API returned malformed indices (got {indices}, expected permutation of 0..{len(texts) - 1}) — refusing to misalign vectors.","messagePattern":"OpenAI API returned malformed indices \\(got (.+?), expected permutation of 0\\.\\.(.+?)\\) — refusing to misalign vectors\\.","errorType":"http","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"code_review_graph/embeddings.py","lineNumber":540,"sourceCode":"                # compatible gateways re-order results or drop entries on\n                # partial failure, and others omit `index` entirely. Three\n                # disjoint cases:\n                #   1. All items have a valid int ``index``: must form a\n                #      permutation of 0..N-1, then sort and use.\n                #   2. NO item carries an ``index`` field: trust server\n                #      order, only verify count matches.\n                #   3. Anything in between (partial indices, str indices,\n                #      missing on some): refuse. Zipping server order in\n                #      that case would happily misalign the indexed items.\n                any_has_index = any(\"index\" in item for item in data)\n                all_int_index = all(\n                    isinstance(item.get(\"index\"), int) for item in data\n                )\n                if all_int_index:\n                    expected = set(range(len(texts)))\n                    indices = [int(item[\"index\"]) for item in data]\n                    if len(set(indices)) != len(indices) or set(indices) != expected:\n                        raise RuntimeError(\n                            \"OpenAI API returned malformed indices \"\n                            f\"(got {indices}, expected permutation of \"\n                            f\"0..{len(texts) - 1}) — refusing to misalign vectors.\"\n                        )\n                    data = sorted(data, key=lambda item: int(item[\"index\"]))\n                elif not any_has_index:\n                    if len(data) != len(texts):\n                        raise RuntimeError(\n                            f\"OpenAI API returned {len(data)} embeddings for \"\n                            f\"{len(texts)} inputs with no index field — \"\n                            \"refusing to misalign vectors.\"\n                        )\n                else:\n                    # Mixed: some items have index, others don't (or carry\n                    # non-int index). Server order would silently misplace\n                    # the indexed items, so we refuse.\n                    raise RuntimeError(\n                        \"OpenAI API returned mixed indexed/unindexed data — \"","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/tirth8205/code-review-graph/blob/b58668751ab0c7670c078cf7cbd4d1f5b8e54f81/code_review_graph/embeddings.py#L522-L558","documentation":"The provider validates that when every returned embedding item carries an integer `index`, those indices must form an exact permutation of 0..N-1 matching the input texts. If indices are duplicated, out of range, or incomplete, it raises this RuntimeError rather than risk pairing vectors with the wrong texts — embeddings are positional, so misalignment would silently corrupt semantic search.","triggerScenarios":"embed() against a gateway that returns all items indexed but with duplicated indices, missing indices, or values outside 0..len(texts)-1 (e.g. index starting at 1, or dropped items).","commonSituations":"Custom OpenAI-compatible servers with off-by-one index bugs, batch truncation under load, or gateways that re-index after dropping failed items.","solutions":["Check gateway/proxy logs: it likely dropped or mislabeled items in the batch","Reduce batch size to see if the gateway handles smaller batches correctly","Fix or patch the gateway so data[i].index covers exactly 0..N-1","Report/upgrade the gateway — its embeddings response violates the OpenAI spec"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# Split large batches: gateways are more likely to drop/misindex big batches\nbatches = [texts[i:i+64] for i in range(0, len(texts), 64)]\nvecs = [provider.embed(b) for b in batches]","typeGuard":null,"tryCatchPattern":"try:\n    vecs = provider.embed(batch)\nexcept RuntimeError as e:\n    if \"malformed indices\" in str(e):\n        # halve batch and retry to dodge gateway index bugs\n        mid = max(1, len(batch)//2)\n        vecs = provider.embed(batch[:mid]) + provider.embed(batch[mid:])\n    else:\n        raise","preventionTips":["Use moderate batch sizes (32–128) against third-party OpenAI-compatible gateways","Run a canary batch through a new gateway and assert len(result) == len(inputs)","Treat any 'refusing to misalign' error as a server bug — report it, don't work around silently"],"tags":["python","openai","embeddings","index-validation","misalignment-guard"],"backgroundTag":"response-index-validation","analyzedSha":"b58668751ab0c7670c078cf7cbd4d1f5b8e54f81","analyzedAt":"2026-08-28T13:19:08.966Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}