run-llama/llama_index · error · ValueError

Node must have a tool_name in metadata.

Error message

Node must have a tool_name in metadata.

What it means

default_node_to_metadata_fn converts a retrieved Node into ToolMetadata for the deprecated RetrieverRouterQueryEngine. It requires the node metadata dict to contain a 'tool_name' key, which becomes the tool name; the node text becomes the description. Missing key raises ValueError.

Source

Thrown at llama-index-core/llama_index/core/query_engine/router_query_engine.py:260

            # add selected result
            final_response.metadata = final_response.metadata or {}
            final_response.metadata["selector_result"] = result

            query_event.on_end(payload={EventPayload.RESPONSE: final_response})

        return final_response


def default_node_to_metadata_fn(node: BaseNode) -> ToolMetadata:
    """
    Default node to metadata function.

    We use the node's text as the Tool description.

    """
    metadata = node.metadata or {}
    if "tool_name" not in metadata:
        raise ValueError("Node must have a tool_name in metadata.")
    return ToolMetadata(name=metadata["tool_name"], description=node.get_content())


class RetrieverRouterQueryEngine(BaseQueryEngine):
    """
    Retriever-based router query engine.

    NOTE: this is deprecated, please use our new ToolRetrieverRouterQueryEngine

    Use a retriever to select a set of Nodes. Each node will be converted
    into a ToolMetadata object, and also used to retrieve a query engine, to form
    a QueryEngineTool.

    NOTE: this is a beta feature. We are figuring out the right interface
    between the retriever and query engine.

    Args:
        selector (BaseSelector): A selector that chooses one out of many options based

View on GitHub (pinned to afd0fef371)

Solutions

  1. Add metadata={"tool_name": "..."} to each node/document before indexing so default_node_to_metadata_fn can map it
  2. Pass a custom node_to_metadata_fn to RetrieverRouterQueryEngine that derives a tool name without requiring 'tool_name'
  3. Migrate to ToolRetrieverRouterQueryEngine, which routes over QueryEngineTool objects and does not need node metadata

Example fix

// before
doc = Document(text="Handles billing questions")
index = SummaryIndex.from_documents([doc])
router = RetrieverRouterQueryEngine(retriever=index.as_retriever(), node_to_query_engine_fn=fn)

// after
doc = Document(
    text="Handles billing questions",
    metadata={"tool_name": "billing_engine"},
)
index = SummaryIndex.from_documents([doc])
router = RetrieverRouterQueryEngine(retriever=index.as_retriever(), node_to_query_engine_fn=fn)
Defensive patterns

Strategy: validation

Validate before calling

def node_has_tool_name(node) -> bool:
    return bool((node.metadata or {}).get("tool_name"))

assert all(node_has_tool_name(n) for n in routing_index.docstore.docs.values()), \
    "every routing node needs metadata['tool_name']"

Type guard

from llama_index.core.schema import BaseNode

def is_routable_node(node: BaseNode) -> bool:
    """Node can be converted by default_node_to_metadata_fn."""
    return "tool_name" in (node.metadata or {})

Prevention

When it happens

Trigger: Building RetrieverRouterQueryEngine over an index whose nodes lack metadata['tool_name'] while using the default node_to_query_engine_fn/metadata conversion (i.e. not supplying a custom node_to_metadata_fn or custom node_to_query_engine_fn).

Common situations: Indexing documents without per-node metadata, or migrating from an old workflow where tool_name was injected into node metadata. The class itself is deprecated in favor of ToolRetrieverRouterQueryEngine.

Related errors


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