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
- Make root_id exactly equal to a key in retriever_dict, typically the id_ of the root IndexNode: RecursiveRetriever('root', {'root': vector_retriever, ...}).
- Print retriever_dict.keys() and compare with the root IndexNode id_ before construction.
- 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
- Derive root_id and dict keys from one constant in your code.
- Unit-test that root_id resolves before running queries.
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
- Retriever and query engine ids must not overlap.
- Object {obj} is not retrievable.
- Unknown retriever mode: {retriever_mode}
- Unknown retriever mode: {retriever_mode}
- Multimodal synthesis requires a chat LLM.
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/7ad5a5c8bb1e7585.
Report an issue: GitHub.