{"record":{"id":"b3c1d7ba9bea62e2","repo":"deepset-ai/haystack","slug":"pythoncodesplitter-only-works-with-text-documents","errorCode":null,"errorMessage":"PythonCodeSplitter only works with text documents but content for document ID {doc.id} is None.","messagePattern":"PythonCodeSplitter only works with text documents but content for document ID (.+?) is None\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/preprocessors/python_code_splitter.py","lineNumber":581,"sourceCode":"\n    @component.output_types(documents=list[Document])\n    def run(self, documents: list[Document]) -> dict[str, list[Document]]:\n        \"\"\"\n        Split each Python source ``Document`` into syntax-aware chunks.\n\n        :param documents: Documents whose ``content`` is Python source code. Each\n            document's ``meta`` is propagated onto its chunks.\n        :returns: ``{\"documents\": [...]}`` where each chunk's meta additionally carries\n            ``source_id``, ``split_id``, ``start_line``, ``end_line``, ``unit_kinds`` and\n            - where applicable - ``include_classes``, ``decorators``, ``docstrings``,\n            ``secondary_split``.\n        :raises ValueError: If any document's content is ``None``.\n        :raises TypeError: If any document's content is not a string.\n        :raises SyntaxError: If a document's content is not valid Python.\n        \"\"\"\n        for doc in documents:\n            if doc.content is None:\n                raise ValueError(\n                    f\"PythonCodeSplitter only works with text documents but content for document ID {doc.id} is None.\"\n                )\n            if not isinstance(doc.content, str):\n                raise TypeError(\"PythonCodeSplitter only works with text documents (str content).\")\n\n        final_docs: list[Document] = []\n        for doc in documents:\n            assert doc.content is not None  # narrowed by the loop above\n            if not doc.content.strip():\n                logger.warning(\"Document ID {doc_id} has empty content. Skipping this document.\", doc_id=doc.id)\n                continue\n\n            units = self._extract_units(doc.content)\n            if not units:\n                continue\n\n            chunks = self._merge_units(units)\n            split_id = 0","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/preprocessors/python_code_splitter.py#L563-L599","documentation":"PythonCodeSplitter.run() rejects documents whose content is None because it must parse and split Python source text. This documents the input contract: only text documents (str content) are supported, and the check raises before any processing happens.","triggerScenarios":"Running the component with documents produced by converters/extractors that failed silently and set content=None, or manually constructed Document(content=None) passed into the 'documents' input.","commonSituations":"Pipeline where an upstream TextFileToDocument/extractor yields empty results for binary or unreadable files; connecting a DocumentCreator that omits content; multi-format ingestion where non-Python/binary files slip in.","solutions":["Filter documents before the splitter: docs = [d for d in docs if d.content is not None].","Fix the upstream converter so it never emits content=None (check file paths and extraction logic).","Use DocumentSplitter for generic text if content may be non-Python; ensure only valid source docs reach this splitter."],"exampleFix":"// before\nresult = splitter.run(documents=all_docs)\n// after\nvalid = [d for d in all_docs if d.content is not None]\nresult = splitter.run(documents=valid)","handlingStrategy":"type-guard","validationCode":"invalid = [d.id for d in documents if d.content is None]\nif invalid:\n    raise ValueError(f'Documents with None content: {invalid}')","typeGuard":"def has_text(doc) -> bool:\n    return doc.content is not None\n\ndocuments = [d for d in documents if has_text(d)]","tryCatchPattern":"try:\n    result = splitter.run(documents=docs)\nexcept ValueError as e:\n    logger.error('Non-text document in input: %s', e)\n    result = splitter.run(documents=[d for d in docs if d.content is not None])","preventionTips":["Filter out None-content documents right after conversion steps.","Check upstream extractors for silent failures on unreadable files.","Log-and-skip bad documents instead of routing them into the splitter."],"tags":["python","haystack","document-content","type-mismatch"],"backgroundTag":"invalid-document-content","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}