{"record":{"id":"76eb806840fe51b4","repo":"run-llama/llama_index","slug":"ref-doc-id-of-node-cannot-be-none-when-building-a-76eb80","errorCode":null,"errorMessage":"ref_doc_id of node cannot be None when building a document summary index","messagePattern":"ref_doc_id of node cannot be None when building a document summary index","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/indices/document_summary/base.py","lineNumber":175,"sourceCode":"            doc_id (str): A document id.\n\n        \"\"\"\n        if doc_id not in self._index_struct.doc_id_to_summary_id:\n            raise ValueError(f\"doc_id {doc_id} not in index\")\n        summary_id = self._index_struct.doc_id_to_summary_id[doc_id]\n        return self.docstore.get_node(summary_id).get_content()\n\n    def _add_nodes_to_index(\n        self,\n        index_struct: IndexDocumentSummary,\n        nodes: Sequence[BaseNode],\n        show_progress: bool = False,\n    ) -> None:\n        \"\"\"Add nodes to index.\"\"\"\n        doc_id_to_nodes = defaultdict(list)\n        for node in nodes:\n            if node.ref_doc_id is None:\n                raise ValueError(\n                    \"ref_doc_id of node cannot be None when building a document \"\n                    \"summary index\"\n                )\n            doc_id_to_nodes[node.ref_doc_id].append(node)\n\n        summary_node_dict = {}\n        items = doc_id_to_nodes.items()\n        iterable_with_progress = get_tqdm_iterable(\n            items, show_progress, \"Summarizing documents\"\n        )\n\n        for doc_id, nodes in iterable_with_progress:\n            print(f\"current doc id: {doc_id}\")\n            nodes_with_scores = [NodeWithScore(node=n) for n in nodes]\n            # get the summary for each doc_id\n            summary_response = self._response_synthesizer.synthesize(\n                query=self._summary_query,\n                nodes=nodes_with_scores,","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/indices/document_summary/base.py#L157-L193","documentation":"DocumentSummaryIndex groups nodes by their ref_doc_id (the source document id) to build per-document summaries. During _add_nodes_to_index, any node whose ref_doc_id is None cannot be attributed to a document, so the build fails immediately with ValueError. Nodes parsed through the standard node-parser pipeline always carry ref_doc_id; hand-constructed nodes often don't.","triggerScenarios":"Building DocumentSummaryIndex.from_documents with a custom transformation that returns TextNode objects built directly (no relationships); inserting nodes via index.insert_nodes where nodes lack a SOURCE relationship; loading nodes from external storage without restoring relationships.","commonSituations":"Custom node pipelines that create TextNode(text=...) manually; caching layers that serialize nodes to dicts and lose the Source relationship; converting other frameworks' chunks into llama-index nodes.","solutions":["Build nodes through a node parser: SentenceSplitter().get_nodes_from_documents(docs) — these set ref_doc_id automatically.","If constructing nodes manually, set the source relationship: node.relationships[NodeRelationship.SOURCE] = RelatedNodeInfo(source_id=doc_id) or pass source_node to TextNode.","Filter/reject nodes with ref_doc_id None before insert: nodes = [n for n in nodes if n.ref_doc_id is not None]."],"exampleFix":"# before\nnodes = [TextNode(text=t) for t in chunks]  # no ref_doc_id -> ValueError\nindex = DocumentSummaryIndex(nodes=nodes)\n\n# after\nfrom llama_index.core.schema import TextNode, RelatedNodeInfo, NodeRelationship\nnodes = [\n    TextNode(\n        text=t,\n        relationships={NodeRelationship.SOURCE: RelatedNodeInfo(source_id=f\"doc-{i}\")},\n    )\n    for i, t in enumerate(chunks)\n]\nindex = DocumentSummaryIndex(nodes=nodes)","handlingStrategy":"validation","validationCode":"orphaned = [n.id_ for n in nodes if n.ref_doc_id is None]\nif orphaned:\n    raise ValueError(f\"Nodes missing SOURCE relationship: {orphaned}\")","typeGuard":"def all_nodes_have_source(nodes) -> bool:\n    return all(n.ref_doc_id is not None for n in nodes)","tryCatchPattern":null,"preventionTips":["Generate nodes with node parsers so ref_doc_id is set automatically.","When building nodes manually, always set relationships[NodeRelationship.SOURCE]."],"tags":["document-summary-index","nodes","ref-doc-id","validation"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}