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

  1. Ensure nodes were added with full metadata (`node_to_metadata_dict(..., remove_text=False)`) so `_node_content` is persisted.
  2. If underscore keys were stripped externally, stop filtering them or restore them before conversion.
  3. For legacy dicts, use `legacy_metadata_dict_to_node` which reads the older field layout.
  4. 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

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


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/0adaec0e77f39c5c. Report an issue: GitHub.