run-llama/llama_index · error · KeyError
Node ID {node_id_str} not found in fetched nodes.
Error message
Node ID {node_id_str} not found in fetched nodes. What it means
VectorIndexRetriever._build_nodes raises KeyError(f'Node ID {node_id_str} not found in fetched nodes.') when a query-result id maps via index_struct.nodes_dict to a node id that is absent from fetched_nodes_by_id (the nodes just fetched from the docstore). The mapping exists but the docstore no longer holds that node — the index struct and the docstore are out of sync, typically after the docstore was swapped, partially persisted, or cleaned while the index struct still references the nodes.
Source
Thrown at llama-index-core/llama_index/core/indices/vector_store/retrievers/retriever.py:203
new_nodes: List[BaseNode] = []
if query_result.nodes:
for node in list(query_result.nodes):
node_id_str = str(node.node_id)
if node_id_str in fetched_nodes_by_id:
new_nodes.append(fetched_nodes_by_id[node_id_str])
else:
# We did not fetch a replacement node, so we keep the original node
new_nodes.append(node)
elif query_result.ids:
for node_id in query_result.ids:
if node_id not in self._index.index_struct.nodes_dict:
raise KeyError(f"Node ID {node_id} not found in index. ")
node_id_str = str(self._index.index_struct.nodes_dict[node_id])
if node_id_str in fetched_nodes_by_id:
new_nodes.append(fetched_nodes_by_id[node_id_str])
else:
raise KeyError(
f"Node ID {node_id_str} not found in fetched nodes. "
)
elif query_result.ids is None and query_result.nodes is None:
raise ValueError(
"Vector store query result should return at least one of nodes or ids."
)
return new_nodes
def _convert_nodes_to_scored_nodes(
self, query_result: VectorStoreQueryResult
) -> List[NodeWithScore]:
"""Create scored nodes from the vector store query result."""
node_with_scores: List[NodeWithScore] = []
for ind, node in enumerate(list(query_result.nodes or [])):
score: Optional[float] = None
if query_result.similarities is not None:
score = query_result.similarities[ind]View on GitHub (pinned to afd0fef371)
Solutions
- Re-ingest into a clean storage context so vector store, index_struct, and docstore are written together.
- When reloading, load StorageContext.from_defaults(persist_dir=...) from one directory containing all artifacts from the same write.
- If the docstore is authoritative, rebuild the index struct from the docstore's nodes.
Example fix
# before
storage = StorageContext.from_defaults(vector_store=store) # docstore from elsewhere
index = load_index_from_storage(storage)
nodes = index.as_retriever().retrieve("q") # KeyError: ... not found in fetched nodes
# after
# re-ingest once, persist everything together
storage = StorageContext.from_defaults(vector_store=store)
index = VectorStoreIndex.from_documents(docs, storage_context=storage)
storage.persist(persist_dir="./storage")
# later: storage = StorageContext.from_defaults(persist_dir="./storage") Defensive patterns
Strategy: try-catch
Validate before calling
def docstore_covers_index_nodes(index) -> bool:
node_ids = set(index.index_struct.nodes_dict.values())
have = set(index.docstore.get_all_document_holder().keys()) if hasattr(index.docstore, "get_all_document_holder") else set()
return node_ids <= have or index.docstore.get_nodes(list(node_ids)[:5]) is not None Try / catch
try:
nodes = retriever.retrieve(query_str)
except KeyError as e:
if "not found in fetched nodes" in str(e):
raise RuntimeError(
"docstore/index_struct mismatch: rebuild the index with a single consistent StorageContext"
) from e
raise Prevention
- Persist all storage artifacts (index_struct, docstore, vector store) atomically from one StorageContext.persist().
- Never mix artifacts from different runs or persist_dirs.
- After partial deletes or migrations, rebuild the index rather than patching one artifact.
When it happens
Trigger: Loading storage where index_struct.json was persisted but docstore.json is stale/missing nodes; deleting nodes from the docstore directly without updating the index; mixing StorageContexts from different runs (vector store + index struct from run A, docstore from run B).
Common situations: Persisting only part of the storage context; manual docstore edits; version-migration scripts that rebuilt one artifact but not the others.
Related errors
- Node ID {node_id} not found in index.
- First argument to Readability constructor should be a docume
- Aborting parsing document; {numTags} elements found
- Command failed: {command} {result.stderr}
- Git command failed: {result.stderr}
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/ec5ef9defe7d55a0.
Report an issue: GitHub.