run-llama/llama_index · error · ValueError

Only one of nodes or index_struct can be provided.

Error message

Only one of nodes or index_struct can be provided.

What it means

BaseIndex's constructor forbids supplying both a populated nodes list and an index_struct. nodes means 'build a fresh index from these nodes' while index_struct means 'attach to an existing index skeleton'; providing both is contradictory and the constructor rejects it with ValueError.

Source

Thrown at llama-index-core/llama_index/core/indices/base.py:52

    index_struct_cls: Type[IS]

    def __init__(
        self,
        nodes: Optional[Sequence[BaseNode]] = None,
        objects: Optional[Sequence[IndexNode]] = None,
        index_struct: Optional[IS] = None,
        storage_context: Optional[StorageContext] = None,
        callback_manager: Optional[CallbackManager] = None,
        transformations: Optional[List[TransformComponent]] = None,
        show_progress: bool = False,
        **kwargs: Any,
    ) -> None:
        """Initialize with parameters."""
        if index_struct is None and nodes is None and objects is None:
            raise ValueError("One of nodes, objects, or index_struct must be provided.")
        if index_struct is not None and nodes is not None and len(nodes) >= 1:
            raise ValueError("Only one of nodes or index_struct can be provided.")
        # This is to explicitly make sure that the old UX is not used
        if nodes is not None and len(nodes) >= 1 and not isinstance(nodes[0], BaseNode):
            if isinstance(nodes[0], Document):
                raise ValueError(
                    "The constructor now takes in a list of Node objects. "
                    "Since you are passing in a list of Document objects, "
                    "please use `from_documents` instead."
                )
            else:
                raise ValueError("nodes must be a list of Node objects.")

        self._storage_context = storage_context or StorageContext.from_defaults()
        self._docstore = self._storage_context.docstore
        self._show_progress = show_progress
        self._vector_store = self._storage_context.vector_store
        self._graph_store = self._storage_context.graph_store
        self._callback_manager = callback_manager or Settings.callback_manager

View on GitHub (pinned to afd0fef371)

Solutions

  1. Pick one pattern: pass nodes to build new, or pass index_struct to attach existing — not both.
  2. In subclass constructors, only forward nodes when the caller actually supplied them (guard with `nodes=nodes if nodes else None`).
  3. To add data to an existing index, construct with index_struct and then call index.insert(...) / index.refresh(...) instead of passing nodes.
  4. Use from_documents or from_nodes factories which handle the contract for you.

Example fix

# before
index = VectorStoreIndex(
    nodes=nodes,
    index_struct=loaded_index_struct,  # both supplied -> ValueError
)

# after
index = VectorStoreIndex(index_struct=loaded_index_struct)
index.insert_nodes(nodes)  # add new data via the insert API
Defensive patterns

Strategy: validation

Validate before calling

if index_struct is not None:
    nodes = None  # attach mode; use index.insert_nodes() for new data
elif nodes is None:
    raise ValueError("Need nodes or index_struct")

Prevention

When it happens

Trigger: Calling an index constructor with both nodes=[...] and index_struct=... where nodes has length >= 1; copy/paste between the two construction patterns; wrapper code that always passes index_struct AND forwards user-supplied nodes.

Common situations: Migrating from the old nodes-based construction to index_struct-based construction and leaving both in the call; custom index subclasses whose __init__ defaults build an index_struct and then also forward nodes unconditionally.

Related errors


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