run-llama/llama_index · error · ValueError
Source object must be a single RelatedNodeInfo object
Error message
Source object must be a single RelatedNodeInfo object
What it means
TextNode.source_node reads relationships[NodeRelationship.SOURCE] and requires it to be a single RelatedNodeInfo, not a list. The SOURCE relationship is singular by schema contract (each node has at most one source document), so a list value is treated as malformed node data and raises ValueError.
Source
Thrown at llama-index-core/llama_index/core/schema.py:403
@node_id.setter
def node_id(self, value: str) -> None:
self.id_ = value
@property
def source_node(self) -> Optional[RelatedNodeInfo]:
"""
Source object node.
Extracted from the relationships field.
"""
if NodeRelationship.SOURCE not in self.relationships:
return None
relation = self.relationships[NodeRelationship.SOURCE]
if isinstance(relation, list):
raise ValueError("Source object must be a single RelatedNodeInfo object")
return relation
@property
def prev_node(self) -> Optional[RelatedNodeInfo]:
"""Prev node."""
if NodeRelationship.PREVIOUS not in self.relationships:
return None
relation = self.relationships[NodeRelationship.PREVIOUS]
if not isinstance(relation, RelatedNodeInfo):
raise ValueError("Previous object must be a single RelatedNodeInfo object")
return relation
@property
def next_node(self) -> Optional[RelatedNodeInfo]:
"""Next node."""
if NodeRelationship.NEXT not in self.relationships:
return NoneView on GitHub (pinned to afd0fef371)
Solutions
- Set the SOURCE relationship to a single RelatedNodeInfo object, not a list
- If you loaded the node from JSON, fix the serialized form: "1": {...} not "1": [{...}]
- Write a normalization pass over relationships before ingest that unwraps one-element lists for SOURCE
Example fix
# before node.relationships[NodeRelationship.SOURCE] = [RelatedNodeInfo(node_id=doc_id)] # after node.relationships[NodeRelationship.SOURCE] = RelatedNodeInfo(node_id=doc_id)
Defensive patterns
Strategy: validation
Validate before calling
rel = node.relationships.get(NodeRelationship.SOURCE)
if isinstance(rel, list):
raise TypeError("SOURCE must be singular; fix ingestion") # or unwrap: rel[0] if len(rel)==1 Type guard
from llama_index.core.schema import RelatedNodeInfo
from llama_index.core.schema import NodeRelationship
def has_valid_source(node) -> bool:
rel = node.relationships.get(NodeRelationship.SOURCE)
return rel is None or isinstance(rel, RelatedNodeInfo) Prevention
- Never reuse the CHILD list pattern for SOURCE
- Normalize relationship shapes in one place during ingestion
- Add schema assertions in tests for custom node builders
When it happens
Trigger: Manually setting node.relationships[NodeRelationship.SOURCE] = [RelatedNodeInfo(...), ...], or loading/deserializing nodes whose SOURCE relation was serialized as a list; then calling .source_node or legacy .ref_doc_id.
Common situations: Custom node builders or ETL code that reuses the CHILD pattern (which is a list) for SOURCE; nodes round-tripped through older versions or hand-written JSON where SOURCE ended up as an array.
Related errors
- Previous object must be a single RelatedNodeInfo object
- Next object must be a single RelatedNodeInfo object
- Parent object must be a single RelatedNodeInfo object
- Child objects must be a list of RelatedNodeInfo objects.
- embedding not set.
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/d6bc24db7dd7fc90.
Report an issue: GitHub.