RyanCodrai/turbovec · error · ValueError
nodes have empty embeddings (dim 0); check the embed model t
Error message
nodes have empty embeddings (dim 0); check the embed model that produced them
What it means
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.
Source
Thrown at turbovec-python/python/turbovec/llama_index.py:370
except ValueError:
seen: set[str] = set()
dup = next(nid for nid in node_ids if nid in seen or seen.add(nid))
raise ValueError(
f"duplicate node_id {dup!r} appears multiple times "
"in the input batch; deduplicate before calling add()"
) from None
embeddings = [node.get_embedding() for node in nodes]
vectors = np.asarray(embeddings, dtype=np.float32)
if vectors.ndim != 2:
raise ValueError(
f"expected 2D embedding batch, got {vectors.ndim}D"
)
# A batch of empty per-node embeddings has shape (N, 0) — 2D, so
# it passes the ndim guard, then dies deep in the index kernel
# with an opaque buffer-length error. Name the real cause instead.
if vectors.shape[1] == 0:
raise ValueError(
"nodes have empty embeddings (dim 0); check the embed "
"model that produced them"
)
# Build every side-car payload BEFORE mutating any state, so a
# payload failure (e.g. non-serializable metadata) leaves the
# store untouched. `metadata` and `ref_doc_id` are kept at top
# level for fast filter / doc-id lookup (queries hit these on
# every hit; parsing _node_content per hit would be wasteful).
# `node_dict` is the framework's canonical metadata representation
# (`_node_content` + `_node_type` + original metadata keys),
# which `metadata_dict_to_node` reconstructs into a full
# BaseNode — preserving relationships (PREVIOUS / NEXT /
# PARENT / CHILD), excluded_*_metadata_keys, template fields,
# start/end_char_idx and mimetype on retrieval. The narrow
# `{text, metadata, ref_doc_id}` schema we used to keep lost
# all of those silently.
payloads = [_payload_for(node) for node in nodes]
View on GitHub (pinned to ccab9f325e)
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)
Example fix
// before store.add(nodes) // after assert all(len(n.get_embedding()) > 0 for n in nodes), "node embeddings are empty" store.add(nodes)
Defensive patterns
Strategy: validation
Validate before calling
if not nodes or any(len(n.get_embedding()) == 0 for n in nodes):
raise ValueError("empty or missing embeddings before store.add()") Type guard
def embeddings_present(nodes) -> bool:
return bool(nodes) and all(n.get_embedding() is not None and len(n.get_embedding()) > 0 for n in nodes) Try / catch
try:
store.add(nodes)
except ValueError as e:
if "empty embeddings" in str(e):
raise RuntimeError("embed model produced empty vectors; check model config and input text") from e
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- duplicate id in batch: {k!r}
- {prefix} {version}; this turbovec accepts versions {list(com
- failed to embed {len(missing)} document(s): {ids}
- expected 2D embedding batch, got {vectors.ndim}D
- node embedding dim {vectors.shape[1]} does not match index d
AI-assisted analysis of RyanCodrai/turbovec@ccab9f325e (2026-09-06).
Data as JSON: /api/errors/b16269aa65cebb6b.
Report an issue: GitHub.