run-llama/llama_index · error · ValueError
Node content not found in metadata dict.
Error message
Node content not found in metadata dict.
What it means
`metadata_dict_to_node` reconstructs a BaseNode from the metadata dict a vector store returns; the serialized node JSON is expected under the `_node_content` key (with `_node_type` selecting the class). If `_node_content` is absent — None or missing — there is nothing to deserialize, so it raises immediately. Typical causes are stores that were never given node content, custom metadata pipelines that strip underscore-prefixed keys, or legacy stores predating the `_node_content` convention.
Source
Thrown at llama-index-core/llama_index/core/vector_stores/utils.py:83
# dump remainder of node_dict to json string
metadata["_node_content"] = json.dumps(node_dict, ensure_ascii=False)
metadata["_node_type"] = node.class_name()
# store ref doc id at top level to allow metadata filtering
# kept for backwards compatibility, will consolidate in future
metadata["document_id"] = node.ref_doc_id or "None" # for Chroma
metadata["doc_id"] = node.ref_doc_id or "None" # for Pinecone, Qdrant, Redis
metadata["ref_doc_id"] = node.ref_doc_id or "None" # for Weaviate
return metadata
def metadata_dict_to_node(metadata: dict, text: Optional[str] = None) -> BaseNode:
"""Common logic for loading Node data from metadata dict."""
node_json = metadata.get("_node_content")
node_type = metadata.get("_node_type")
if node_json is None:
raise ValueError("Node content not found in metadata dict.")
node: BaseNode
if node_type == Node.class_name():
node = Node.from_json(node_json)
elif node_type == IndexNode.class_name():
node = IndexNode.from_json(node_json)
elif node_type == ImageNode.class_name():
node = ImageNode.from_json(node_json)
else:
node = TextNode.from_json(node_json)
if text is not None:
node.set_content(text)
return node
def build_metadata_filter_fn(View on GitHub (pinned to afd0fef371)
Solutions
- Ensure nodes were added with full metadata (`node_to_metadata_dict(..., remove_text=False)`) so `_node_content` is persisted.
- If underscore keys were stripped externally, stop filtering them or restore them before conversion.
- For legacy dicts, use `legacy_metadata_dict_to_node` which reads the older field layout.
- If the store simply has no node content, retrieve the node from the docstore instead of metadata.
Example fix
# before
node = metadata_dict_to_node({"_node_type": "TEXT", "doc_id": "x"}) # ValueError
# after
node = metadata_dict_to_node(store_metadata) # where store_metadata["_node_content"] exists
# or, for old layouts:
node_info, text, ref_doc = legacy_metadata_dict_to_node(old_metadata) Defensive patterns
Strategy: validation
Validate before calling
def metadata_has_node_content(metadata: dict) -> bool:
return metadata.get("_node_content") is not None Try / catch
try:
node = metadata_dict_to_node(metadata)
except ValueError as e:
if "Node content not found" in str(e):
node = index.docstore.get_node(node_id) # fallback
else:
raise Prevention
- Persist nodes with node_to_metadata_dict(remove_text=False) when you plan to rehydrate.
- Never strip underscore-prefixed metadata keys in downstream systems.
- Keep _node_content/_node_type fields out of user-facing filter surfaces.
When it happens
Trigger: Calling `metadata_dict_to_node(metadata)` on a dict lacking `_node_content` — e.g. metadata round-tripped through SimpleVectorStore without stores_text, hand-built metadata dicts, or a store integration that returns only user metadata; also hit via `legacy_metadata_dict_to_node`-adjacent paths when content fields were never persisted.
Common situations: Building VectorStoreIndex with `stores_text=False` or inserting raw embedding tuples without node content; sanitizing metadata for third-party systems that drop underscore keys; upgrading from very old persist formats where node data lived in separate fields; querying stores where content embedding was stored but the JSON blob was not.
Related errors
- Cannot filter stores that were persisted without metadata. P
- No existing {__name__} found at {persist_path}, skipping loa
- Vector store integrations that store text in the vector stor
- Unable to load from persist dir. The object_node_mapping can
- Objs cannot be loaded.
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/0adaec0e77f39c5c.
Report an issue: GitHub.