run-llama/llama_index · error · KeyError
Node ID 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.
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 not found in index.
- Aborting parsing document;
- Cannot initialize from a vector store that does not store…
- Cannot initialize from a vector store that does not store…
- Command failed
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/ec5ef9defe7d55a0.
Report an issue: GitHub.
Appendix: 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)