{"record":{"id":"00ff53ebdf8efbc5","repo":"zylon-ai/private-gpt","slug":"zpgt-ingest-no-valid-nodes-error","errorCode":"zpgt.ingest.no_valid_nodes.error","errorMessage":"zpgt.ingest.no_valid_nodes.error","messagePattern":"zpgt\\.ingest\\.no_valid_nodes\\.error","errorType":"error_code","errorClass":"InvalidFileError","httpStatus":400,"severity":"error","filePath":"private_gpt/components/ingest/ingest_component.py","lineNumber":279,"sourceCode":"            )\n\n            # 1. Delete previous nodes, to avoid duplicates\n            self.node_store_component.delete_filtered_nodes(\n                collection=collection,\n                artifacts=[artifact],\n            )\n\n            # 2. Insert nodes\n            inserted_nodes: Sequence[BaseNode] = []\n            if use_async:\n                inserted_nodes = asyncio.run(\n                    extended_index.ainsert(nodes, notify=notify_publisher)\n                )\n            else:\n                inserted_nodes = extended_index.insert(nodes, notify=notify_publisher)\n\n            if not inserted_nodes:\n                raise InvalidFileError(\n                    errors=[IngestionLoadErrors.NO_VALID_NODES], warnings=warnings\n                )\n\n            index.summary = ArtifactIndexStatus.POPULATED.value\n            index.set_index_id(index_id)\n            index.storage_context.persist(persist_dir=local_data_path / collection)\n            logger.info(\"Finished loading index %s with %d nodes\", index_id, len(nodes))\n","sourceCodeStart":261,"sourceCodeEnd":287,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/ingest/ingest_component.py#L261-L287","documentation":"InvalidFileError raised when extended_index.insert()/ainsert() returns an empty result — the document parsed into nodes, but the vector store inserted none of them. Carries the IngestionLoadErrors.NO_VALID_NODES code (zpgt.ingest.no_valid_nodes.error) and the warnings list. At this point the index status is not advanced to POPULATED, so the collection stays empty for this artifact.","triggerScenarios":"Running _ingest with use_async true or false where insert(nodes, notify=...) returns [] — e.g. all nodes filtered out by the store's transforms/embedding rules, empty text nodes, unsupported node types, or a store silently rejecting the batch.","commonSituations":"Documents whose extracted text is empty or whitespace-only (scanned PDFs without OCR); node transforms dropping everything; dimension mismatch between embedding output and the vector store collection; store insert hooks filtering by metadata; silent failures in a custom ExtendedIndex.","solutions":["Check the warnings attached to the error and the parse result — they usually name why nodes were dropped","Verify the document actually contains extractable text (run OCR for scanned PDFs)","Confirm the embedding model's dimensions match the target collection/schema","Log the nodes passed to insert to see whether they were empty before reaching the store"],"exampleFix":"# before: insert returns [] -> InvalidFileError(NO_VALID_NODES)\nnodes = result.nodes\ninserted = extended_index.insert(nodes, notify=notify_publisher)\n\n# after\nclean = [n for n in nodes if (n.get_content() or '').strip()]\nif not clean:\n    raise ValueError('document has no extractable text')\ninserted = extended_index.insert(clean, notify=notify_publisher)","handlingStrategy":"try-catch","validationCode":"contentful = [n for n in nodes if (n.get_content() or '').strip()]\nif not contentful:\n    raise ValueError('no nodes with non-empty text; document likely lacks extractable text')","typeGuard":null,"tryCatchPattern":"try:\n    component._ingest(file, collection)\nexcept InvalidFileError as e:\n    if IngestionLoadErrors.NO_VALID_NODES in (e.errors or []):\n        return error_response(422, 'no valid nodes produced', warnings=e.warnings)\n    raise","preventionTips":["Reject empty/whitespace-only and scanned-no-OCR documents before ingest","Verify embedding dimensions match the target collection schema","Log node counts passed to insert vs returned to catch silent store-side filtering"],"tags":["ingest","vector-store","empty-input","parsing"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}