run-llama/llama_index · error · ValueError
Metadata must be set
Error message
Metadata must be set
What it means
SimpleToolNodeMapping._from_node resolves a retrieved node back to the original tool by looking up node.metadata['name'] in an in-memory dict. It first requires node.metadata to be non-None and raises ValueError('Metadata must be set') otherwise; note that even with metadata set, a missing 'name' key will then raise KeyError.
Source
Thrown at llama-index-core/llama_index/core/objects/tool_node_mapping.py:95
self._tools = {tool.metadata.name: tool for tool in objs}
@classmethod
def from_objects(
cls, objs: Sequence[BaseTool], *args: Any, **kwargs: Any
) -> "BaseObjectNodeMapping":
return cls(objs)
def _add_object(self, tool: BaseTool) -> None:
self._tools[tool.metadata.name] = tool
def to_node(self, tool: BaseTool) -> TextNode:
"""To node."""
return convert_tool_to_node(tool)
def _from_node(self, node: BaseNode) -> BaseTool:
"""From node."""
if node.metadata is None:
raise ValueError("Metadata must be set")
return self._tools[node.metadata["name"]]
class BaseQueryToolNodeMapping(BaseObjectNodeMapping[QueryEngineTool]):
"""Base query tool node mapping."""
@classmethod
def from_persist_dir(
cls,
persist_dir: str = DEFAULT_PERSIST_DIR,
obj_node_mapping_fname: str = DEFAULT_PERSIST_FNAME,
) -> "BaseQueryToolNodeMapping":
raise NotImplementedError(
"This object node mapping does not support persist method."
)
@property
def obj_node_mapping(self) -> Dict[int, Any]:View on GitHub (pinned to afd0fef371)
Solutions
- Create nodes via the mapping (mapping.to_node(tool)) or convert_tool_to_node so metadata['name'] is populated
- Before from_node, check `if not node.metadata or 'name' not in node.metadata: raise/skip`
- Ensure transformations don't drop the 'name' metadata key from tool nodes
Example fix
# before
node = TextNode(text="tool: search") # no metadata
tool = mapping.from_node(node) # ValueError: Metadata must be set
# after
node = mapping.to_node(tool) # metadata={'name': 'search', ...}
resolved = mapping.from_node(node) Defensive patterns
Strategy: validation
Validate before calling
if not node.metadata or "name" not in node.metadata:
raise ValueError(f"node {node.id_} missing metadata['name']")
if node.metadata["name"] not in mapping.obj_node_mapping if hasattr(mapping, 'obj_node_mapping') else True:
pass # name not pre-registered; from_node would KeyError
resolved = mapping.from_node(node) Type guard
def node_has_tool_name(node) -> bool:
return bool(node.metadata) and isinstance(node.metadata.get("name"), str) Try / catch
try:
tool = mapping.from_node(node)
except ValueError as e:
if "Metadata must be set" in str(e):
log_and_skip(node)
else:
raise
except KeyError:
log_and_skip(node) # name not in tool dict Prevention
- Create tool nodes via convert_tool_to_node/mapping.to_node only
- Avoid transformations that drop the 'name' metadata key
When it happens
Trigger: Calling mapping.from_node(node) during ObjectIndex/retriever resolution with a node that was constructed without metadata, a node whose metadata was cleared (excluded keys stripped incorrectly), or a synthetic test node.
Common situations: Custom retrieval code that creates TextNodes manually; docstore entries from older versions; tests feeding bare TextNodes into from_node.
Related errors
- Metadata must be set
- Tool name must be set
- Max iterations of {max_iterations} reached! Either something
- No tool calls found, cannot aggregate results.
- Metadata key must be str!
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/d3275f0ba30d4c3b.
Report an issue: GitHub.