{"record":{"id":"1a3053bedb01aa09","repo":"MemPalace/mempalace","slug":"embedding-api-at-self-url-returned-non-object-r","errorCode":null,"errorMessage":"Embedding API at {self._url} returned non-object rows: {e}","messagePattern":"Embedding API at (.+?) returned non-object rows: (.+?)","errorType":"exception","errorClass":"EmbeddingAPIError","httpStatus":null,"severity":"error","filePath":"mempalace/embedding.py","lineNumber":600,"sourceCode":"            )\n        rows = data.get(\"data\")\n        if not isinstance(rows, list):\n            raise EmbeddingAPIError(\n                f\"Embedding API at {self._url} returned no 'data' array: {data.get('error', data)}\"\n            )\n        if len(rows) != n:\n            raise EmbeddingAPIError(\n                f\"Embedding API at {self._url} returned {len(rows)} embeddings for {n} inputs\"\n            )\n        # The endpoint may return rows out of order — sort by index, then\n        # require the indices to be exactly 0..n-1 so positional alignment is\n        # provably correct (a server using absolute or duplicate indices would\n        # otherwise pass the count check yet map vectors to the wrong texts).\n        try:\n            rows = sorted(rows, key=lambda d: d.get(\"index\", -1))\n            indices = [r.get(\"index\") for r in rows]\n        except AttributeError as e:\n            raise EmbeddingAPIError(\n                f\"Embedding API at {self._url} returned non-object rows: {e}\"\n            ) from e\n        if indices != list(range(n)):\n            raise EmbeddingAPIError(\n                f\"Embedding API at {self._url} returned non-contiguous or duplicate \"\n                f\"'index' values; cannot align embeddings with inputs\"\n            )\n        try:\n            arr = np.asarray([r[\"embedding\"] for r in rows], dtype=np.float32)\n        except (KeyError, TypeError, ValueError) as e:\n            raise EmbeddingAPIError(\n                f\"Embedding API at {self._url} returned malformed embeddings: {e}\"\n            ) from e\n        if arr.ndim != 2:\n            raise EmbeddingAPIError(\n                f\"Embedding API at {self._url} returned non-vector embeddings (shape {arr.shape})\"\n            )\n        # L2-normalize so cosine == dot product (collection uses","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/embedding.py#L582-L618","documentation":"Raised by _vectors_from_response when sorting the 'data' rows by their 'index' key raises AttributeError — i.e. one or more rows are not dicts (a string, number, null, or list), so d.get('index') fails. This catches structurally malformed row entries before any positional alignment is attempted, and the original AttributeError is chained for the exact row access that broke.","triggerScenarios":"A server whose data array contains non-object entries, e.g. \"data\": [\"ok\"] or \"data\": [null, {...}], or a hand-written stub returning bare vectors ([0.1, 0.2]) instead of {\"index\": i, \"embedding\": [...]} objects.","commonSituations":"Custom in-house embedding microservices that predate the OpenAI response schema; partially migrated servers; test fixtures with sloppy JSON; servers that append a trailing metadata element to the data array.","solutions":["Curl the endpoint and inspect each element of 'data' — every element must be an object with 'index' and 'embedding' keys","Fix the server or stub to emit row objects: {\"index\": i, \"embedding\": [...]}","If using a third-party proxy that flattens rows, bypass it for the embeddings route","Verify no null/NaN JSON entries are injected by server-side serialization bugs"],"exampleFix":"# stub — before\nreturn {\"data\": [[0.1, 0.2], [0.3, 0.4]]}\n# after\nreturn {\"data\": [\n    {\"index\": 0, \"embedding\": [0.1, 0.2]},\n    {\"index\": 1, \"embedding\": [0.3, 0.4]},\n]}","handlingStrategy":"type-guard","validationCode":"rows = resp.get(\"data\", [])\nassert all(isinstance(r, dict) for r in rows), \"data rows must be objects\"","typeGuard":"def rows_are_objects(data) -> bool:\n    rows = data.get(\"data\") if isinstance(data, dict) else None\n    return isinstance(rows, list) and bool(rows) and all(isinstance(r, dict) for r in rows)","tryCatchPattern":"try:\n    vecs = ef(texts)\nexcept EmbeddingAPIError as e:\n    if \"non-object rows\" in str(e):\n        fix_stub_server_row_shape()  # structural bug — no point retrying","preventionTips":["Stub/prototype servers must emit {\"index\": int, \"embedding\": [floats]} per row","Contract-test your embedding service against the OpenAI schema in CI"],"tags":["embedding","api","validation","response-format"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}