run-llama/llama_index · error · KeyError

Node ID {node_id} not found in index.

Error message

Node ID {node_id} not found in index. 

What it means

VectorIndexRetriever._build_nodes raises KeyError(f'Node ID {node_id} not found in index.') when the vector store returns ids in query_result.ids that are not keys in index.index_struct.nodes_dict. This path only runs when the store returns ids without nodes (stores_text=False): the retriever must map external ids to local nodes via the index struct. A mismatch means the vector store contains vectors whose ids were never registered in this index's nodes_dict — e.g. data written by a different run/index or the index struct not persisted alongside the vector store.

Source

Thrown at llama-index-core/llama_index/core/indices/vector_store/retrievers/retriever.py:198

            unless the node was not found in the docstore, in which case we keep the original node.
        """
        fetched_nodes_by_id: Dict[str, BaseNode] = {
            str(node.node_id): node for node in fetched_nodes
        }
        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] = []

View on GitHub (pinned to afd0fef371)

Solutions

  1. Make the vector store and index struct consistent: clear the store and re-ingest through the same VectorStoreIndex so nodes_dict and store ids match.
  2. When reloading, load the full storage context (index_struct + docstore) that was persisted with that vector store, not just the vector store.
  3. If the store must be shared, use a stores_text=True store so query results carry nodes and the nodes_dict mapping is bypassed.

Example fix

# before
# chroma persisted earlier by another run; index_struct is empty
retriever = VectorIndexRetriever(index)
nodes = retriever.retrieve("query")  # KeyError: Node ID ... not found in index

# after
store.clear()  # or a fresh collection
index = VectorStoreIndex.from_documents(docs, storage_context=StorageContext.from_defaults(vector_store=store))
nodes = index.as_retriever().retrieve("query")
Defensive patterns

Strategy: try-catch

Validate before calling

def store_ids_all_registered(store, index) -> bool:
    """Heavier check; do a cheap canary retrieve instead."""
    return True

def canary_retrieve_ok(retriever, index) -> bool:
    try:
        retriever.retrieve("__canary__")
        return True
    except KeyError:
        return False  # vector store contains ids unknown to index_struct

Try / catch

try:
    nodes = retriever.retrieve(query_str)
except KeyError as e:
    if "not found in index" in str(e):
        # store/index_struct mismatch: re-sync or rebuild
        index = resync_index_from_store(index)
        nodes = index.as_retriever().retrieve(query_str)
    else:
        raise

Prevention

When it happens

Trigger: Vector store pre-populated outside this index (external upserts, another service, another llama-index project) then queried through VectorIndexRetriever; reloading an index where the vector store persisted but the index_struct/docstore did not; partial deletes leaving stale ids in the store.

Common situations: Chroma/Milvus/FAISS files shared across runs; hybrid setups where a separate pipeline writes embeddings; storage_context persist_dir missing .json artifacts while the vector DB retained data.

Related errors


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