run-llama/llama_index · error · ValueError

Root id {root_id} not in retriever_dict, it must be a retrie

Error message

Root id {root_id} not in retriever_dict, it must be a retriever.

What it means

RecursiveRetriever starts traversal at root_id and must find it in retriever_dict, because the root of recursion has to be a retriever (not a query engine or node). __init__ raises ValueError when root_id is not a key of retriever_dict. Keys of retriever_dict are matched against IndexNode ids during traversal, so root_id must be one of those ids too.

Source

Thrown at llama-index-core/llama_index/core/retrievers/recursive_retriever.py:54

        query_engine_dict (Optional[Dict[str, BaseQueryEngine]]): A dictionary of
            id to query engines.

    """

    def __init__(
        self,
        root_id: str,
        retriever_dict: Dict[str, BaseRetriever],
        query_engine_dict: Optional[Dict[str, BaseQueryEngine]] = None,
        node_dict: Optional[Dict[str, BaseNode]] = None,
        callback_manager: Optional[CallbackManager] = None,
        query_response_tmpl: Optional[str] = None,
        verbose: bool = False,
    ) -> None:
        """Init params."""
        self._root_id = root_id
        if root_id not in retriever_dict:
            raise ValueError(
                f"Root id {root_id} not in retriever_dict, it must be a retriever."
            )
        self._retriever_dict = retriever_dict
        self._query_engine_dict = query_engine_dict or {}
        self._node_dict = node_dict or {}

        # make sure keys don't overlap
        if set(self._retriever_dict.keys()) & set(self._query_engine_dict.keys()):
            raise ValueError("Retriever and query engine ids must not overlap.")

        self._query_response_tmpl = query_response_tmpl or DEFAULT_QUERY_RESPONSE_TMPL
        super().__init__(callback_manager, verbose=verbose)

    def _deduplicate_nodes(
        self, nodes_with_score: List[NodeWithScore]
    ) -> List[NodeWithScore]:
        """
        Deduplicate nodes according to node id.

View on GitHub (pinned to afd0fef371)

Solutions

  1. Make root_id exactly equal to a key in retriever_dict, typically the id_ of the root IndexNode: RecursiveRetriever('root', {'root': vector_retriever, ...}).
  2. Print retriever_dict.keys() and compare with the root IndexNode id_ before construction.
  3. When building IndexNodes programmatically, derive both the node id and the dict key from one constant.

Example fix

# before
retriever = RecursiveRetriever(
    "root_id", retriever_dict={"index1": vec_retriever}
)

# after
retriever = RecursiveRetriever(
    "index1", retriever_dict={"index1": vec_retriever}
)
Defensive patterns

Strategy: validation

Validate before calling

assert root_id in retriever_dict, f"root_id {root_id!r} not in {list(retriever_dict)}"

Prevention

When it happens

Trigger: Passing root_id='root' while retriever_dict keys are e.g. {'concepts': ...}; using the IndexNode's text instead of its id_ as root_id; building the dict from a different index than the one whose nodes embed the ids; typos or case mismatch between root_id and dict keys.

Common situations: Compositional/hierarchical RAG (index of IndexNodes pointing at sub-indexes) where the linking id and the dict key drift apart; notebooks evolved incrementally where the root node id changed.

Related errors


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