{"record":{"id":"b16269aa65cebb6b","repo":"RyanCodrai/turbovec","slug":"nodes-have-empty-embeddings-dim-0-check-the-emb","errorCode":null,"errorMessage":"nodes have empty embeddings (dim 0); check the embed model that produced them","messagePattern":"nodes have empty embeddings \\(dim 0\\); check the embed model that produced them","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"turbovec-python/python/turbovec/llama_index.py","lineNumber":370,"sourceCode":"        except ValueError:\n            seen: set[str] = set()\n            dup = next(nid for nid in node_ids if nid in seen or seen.add(nid))\n            raise ValueError(\n                f\"duplicate node_id {dup!r} appears multiple times \"\n                \"in the input batch; deduplicate before calling add()\"\n            ) from None\n\n        embeddings = [node.get_embedding() for node in nodes]\n        vectors = np.asarray(embeddings, dtype=np.float32)\n        if vectors.ndim != 2:\n            raise ValueError(\n                f\"expected 2D embedding batch, got {vectors.ndim}D\"\n            )\n        # A batch of empty per-node embeddings has shape (N, 0) — 2D, so\n        # it passes the ndim guard, then dies deep in the index kernel\n        # with an opaque buffer-length error. Name the real cause instead.\n        if vectors.shape[1] == 0:\n            raise ValueError(\n                \"nodes have empty embeddings (dim 0); check the embed \"\n                \"model that produced them\"\n            )\n        # Build every side-car payload BEFORE mutating any state, so a\n        # payload failure (e.g. non-serializable metadata) leaves the\n        # store untouched. `metadata` and `ref_doc_id` are kept at top\n        # level for fast filter / doc-id lookup (queries hit these on\n        # every hit; parsing _node_content per hit would be wasteful).\n        # `node_dict` is the framework's canonical metadata representation\n        # (`_node_content` + `_node_type` + original metadata keys),\n        # which `metadata_dict_to_node` reconstructs into a full\n        # BaseNode — preserving relationships (PREVIOUS / NEXT /\n        # PARENT / CHILD), excluded_*_metadata_keys, template fields,\n        # start/end_char_idx and mimetype on retrieval. The narrow\n        # `{text, metadata, ref_doc_id}` schema we used to keep lost\n        # all of those silently.\n        payloads = [_payload_for(node) for node in nodes]\n","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/RyanCodrai/turbovec/blob/ccab9f325e6ce2a270a87daf01ae4e443bcf2d49/turbovec-python/python/turbovec/llama_index.py#L352-L388","documentation":"The batch is 2D but its second axis is 0 — every node has a zero-length embedding. This passes the ndim guard but would crash deep inside the Rust index kernel with an opaque buffer error, so the library raises a clear ValueError naming the real cause instead.","triggerScenarios":"Calling add() with nodes whose get_embedding() returns [] or an empty array for every node — e.g. nodes constructed from documents without ever running the embed model, or an embed model configured to skip embedding.","commonSituations":"Forgetting to run an embedding step in a custom ingestion pipeline; an embed model returning [] on failure or empty text; loading nodes from storage without their embeddings.","solutions":["Run the embed model over node content and set node.embedding before add()","Verify embeddings with `all(len(n.get_embedding()) > 0 for n in nodes)` before calling add()","Check the embed model/config isn't silently returning empty vectors (e.g. missing API key, empty text input)"],"exampleFix":"// before\nstore.add(nodes)\n// after\nassert all(len(n.get_embedding()) > 0 for n in nodes), \"node embeddings are empty\"\nstore.add(nodes)","handlingStrategy":"validation","validationCode":"if not nodes or any(len(n.get_embedding()) == 0 for n in nodes):\n    raise ValueError(\"empty or missing embeddings before store.add()\")","typeGuard":"def embeddings_present(nodes) -> bool:\n    return bool(nodes) and all(n.get_embedding() is not None and len(n.get_embedding()) > 0 for n in nodes)","tryCatchPattern":"try:\n    store.add(nodes)\nexcept ValueError as e:\n    if \"empty embeddings\" in str(e):\n        raise RuntimeError(\"embed model produced empty vectors; check model config and input text\") from e\n    raise","preventionTips":["Run the embed step before constructing the vector store","Log embedding dims after embedding to catch empty outputs","Verify the embed model API key and that input texts are non-empty"],"tags":["python","embedding","empty-input","validation"],"backgroundTag":"empty-required-field","analyzedSha":"ccab9f325e6ce2a270a87daf01ae4e443bcf2d49","analyzedAt":"2026-09-06T08:39:18.516Z","contentChangedAt":"2026-09-06T08:39:18.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}