run-llama/llama_index · error · ValueError
Query id {query_id} not found in either `retriever_dict` or
Error message
Query id {query_id} not found in either `retriever_dict` or `query_engine_dict`. What it means
During recursive traversal, when a fetched object's IndexNode id (query_id) points into another node, _get_object looks the id up in node_dict, then retriever_dict, then query_engine_dict. This ValueError means the id matched none of them, i.e. an IndexNode references a target that was never registered with the RecursiveRetriever. It surfaces mid-retrieve, after retrieval has already begun.
Source
Thrown at llama-index-core/llama_index/core/retrievers/recursive_retriever.py:153
additional_nodes.extend(cur_additional_nodes)
# dedup nodes in case some nodes could be retrieved from multiple sources
nodes_to_add = self._deduplicate_nodes(nodes_to_add)
additional_nodes = self._deduplicate_nodes(additional_nodes)
return nodes_to_add, additional_nodes
def _get_object(self, query_id: str) -> RQN_TYPE:
"""Fetch retriever or query engine."""
node = self._node_dict.get(query_id, None)
if node is not None:
return node
retriever = self._retriever_dict.get(query_id, None)
if retriever is not None:
return retriever
query_engine = self._query_engine_dict.get(query_id, None)
if query_engine is not None:
return query_engine
raise ValueError(
f"Query id {query_id} not found in either `retriever_dict` "
"or `query_engine_dict`."
)
def _retrieve_rec(
self,
query_bundle: QueryBundle,
query_id: Optional[str] = None,
cur_similarity: Optional[float] = None,
) -> Tuple[List[NodeWithScore], List[NodeWithScore]]:
"""Query recursively."""
if self._verbose:
print_text(
f"Retrieving with query id {query_id}: {query_bundle.query_str}\n",
color="blue",
)
query_id = query_id or self._root_id
cur_similarity = cur_similarity or 1.0View on GitHub (pinned to afd0fef371)
Solutions
- Register the missing id: add retriever_dict[query_id] = target_retriever (or query_engine_dict[query_id] = engine, or node_dict[query_id] = node) so every IndexNode reference resolves.
- Audit links vs registrations: collect all IndexNode references in your index tree and diff against retriever_dict | query_engine_dict | node_dict keys before querying.
- If the link is stale, rebuild the IndexNode with the correct index_id and re-index.
Example fix
# before
# IndexNode(id_='n1', text='...', index_id='sub2') exists,
# but retriever_dict = {'root': r, 'sub1': r1}
retriever = RecursiveRetriever('root', retriever_dict)
# after
retriever_dict = {'root': r, 'sub1': r1, 'sub2': r2} # every index_id registered
retriever = RecursiveRetriever('root', retriever_dict) Defensive patterns
Strategy: validation
Validate before calling
known_ids = set(retriever_dict) | set(query_engine_dict) | set(node_dict)
# collect every index_id your IndexNodes reference
referenced = {n.index_id for n in index_nodes} # adapt to your tree walk
missing = referenced - known_ids - {root_id}
assert not missing, f"unregistered ids: {missing}" Try / catch
try:
nodes = retriever.retrieve(q)
except ValueError as e:
if "not found in either" in str(e):
raise KeyError(f"IndexNode link unregistered: {e}") from e
raise Prevention
- Register every IndexNode target in retriever_dict/query_engine_dict/node_dict.
- Diff node references against registered ids after loading a persisted index.
- Rebuild IndexNodes whenever you rename dict keys.
When it happens
Trigger: An IndexNode whose index_id/embedding reference (e.g. 'subindex2') has no entry in retriever_dict/query_engine_dict; building the dicts from a subset of the linked indexes; ids serialized into IndexNodes that were renamed after the index was built; using SummaryIndex nodes whose obj ids no longer exist.
Common situations: Persisting an index of IndexNodes and later reconstructing the RecursiveRetriever with an incomplete or renamed mapping; hierarchical RAG where sub-indexes were added/removed between runs; docstring-style examples where the dict keys are 'vector' etc. but nodes reference different ids.
Related errors
- Object {obj} is not retrievable.
- Root id {root_id} not in retriever_dict, it must be a retrie
- Retriever and query engine ids must not overlap.
- Must be a retriever or query engine.
- LLM must be a FunctionCallingLLM
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/db3dd3e4f1bc4d2b.
Report an issue: GitHub.