run-llama/llama_index · error · ValueError

Node {node_id} not found

Error message

Node {node_id} not found

What it means

BaseDocumentStore.get_node delegates to get_document(node_id) and raises this defensive ValueError when the returned object is None despite raise_error being requested. Normally get_document raises 'doc_id ... not found' first, so seeing this specific message means the underlying store returned None without raising (custom/overridden docstore behavior) -- plus a follow-on type check rejects non-Node results.

Source

Thrown at llama-index-core/llama_index/core/storage/docstore/types.py:204

        self, node_id: str, raise_error: Literal[False] = False
    ) -> Optional[BaseNode]: ...

    def get_node(self, node_id: str, raise_error: bool = True) -> Optional[BaseNode]:
        """
        Get node from docstore.

        Args:
            node_id (str): node id
            raise_error (bool): raise error if node_id not found

        """
        doc = self.get_document(node_id, raise_error=raise_error)

        if doc is None:
            # The doc store should have raised an error if the node_id is not found, but it didn't
            # so we raise an error here
            if raise_error:
                raise ValueError(f"Node {node_id} not found")
            return None

        # The document should always be a BaseNode, but we check to be safe
        if not isinstance(doc, BaseNode):
            raise ValueError(f"Document {node_id} is not a Node.")

        return doc

    @overload
    async def aget_node(
        self, node_id: str, raise_error: Literal[True] = True
    ) -> BaseNode: ...

    @overload
    async def aget_node(
        self, node_id: str, raise_error: Literal[False] = False
    ) -> Optional[BaseNode]: ...

View on GitHub (pinned to afd0fef371)

Solutions

  1. Call get_node(node_id, raise_error=False) and handle None when absence is expected.
  2. Pre-check with docstore.document_exists(node_id).
  3. Fix custom get_document overrides to honor raise_error=True by raising, keeping the BaseDocumentStore contract.
  4. Re-ingest or re-sync the docstore if vector-store node IDs point at missing docstore entries.

Example fix

# before
node = docstore.get_node(node_id)  # ValueError: Node ... not found

# after
node = docstore.get_node(node_id, raise_error=False)
if node is None:
    node = None  # skip / re-ingest source document
Defensive patterns

Strategy: validation

Validate before calling

def get_node_or_none(docstore, node_id):
    if not docstore.document_exists(node_id):
        return None
    return docstore.get_node(node_id)

Type guard

def node_exists(docstore, node_id: str) -> bool:
    return docstore.document_exists(node_id)

Try / catch

try:
    node = docstore.get_node(node_id)
except ValueError as e:
    if 'not found' in str(e):
        node = None  # skip stale reference
    else:
        raise

Prevention

When it happens

Trigger: docstore.get_node(node_id) where the node is absent and the concrete get_document implementation returns None instead of raising (e.g. a custom docstore subclass whose get_document ignores raise_error, or raise_error propagation is bypassed); also nodes looked up by a stale ID after deletion.

Common situations: Custom DocumentStore backends that do not honor the raise_error contract; retrieval flows resolving node IDs returned by a vector store after the docstore was partially cleared; tests with mock docstores returning None.

Related errors


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