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

  1. Re-ingest into a clean storage context so vector store, index_struct, and docstore are written together.
  2. When reloading, load StorageContext.from_defaults(persist_dir=...) from one directory containing all artifacts from the same write.
  3. 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

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


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