{"record":{"id":"8a52fe4d2bcea673","repo":"deepset-ai/haystack","slug":"markdownheadersplitter-only-works-with-text-docume","errorCode":null,"errorMessage":"MarkdownHeaderSplitter only works with text documents but content for document ID {doc.id} is None.","messagePattern":"MarkdownHeaderSplitter only works with text documents but content for document ID (.+?) is None\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/preprocessors/markdown_header_splitter.py","lineNumber":365,"sourceCode":"        Run the markdown header splitter with optional secondary splitting.\n\n        :param documents: List of documents to split\n\n        :returns: A dictionary with the following key:\n            - `documents`: List of documents with the split texts. Each document includes:\n                - A metadata field `source_id` to track the original document.\n                - A metadata field `page_number` to track the original page number.\n                - A metadata field `split_id` to identify the split chunk index within its parent document.\n                - All other metadata copied from the original document.\n        :raises ValueError: If a document has `None` content.\n        :raises TypeError: If a document's content is not a string.\n        \"\"\"\n        if self.secondary_split and not self._is_warmed_up:\n            self.warm_up()\n        # validate input documents\n        for doc in documents:\n            if doc.content is None:\n                raise ValueError(\n                    \"MarkdownHeaderSplitter only works with text documents but content for document ID\"\n                    f\" {doc.id} is None.\"\n                )\n            if not isinstance(doc.content, str):\n                raise TypeError(\"MarkdownHeaderSplitter only works with text documents (str content).\")\n\n        final_docs = []\n        for doc in documents:\n            # handle empty documents\n            if not doc.content or not doc.content.strip():  # avoid counting whitespace as content\n                if self.skip_empty_documents:\n                    logger.warning(\"Document ID {doc_id} has an empty content. Skipping this document.\", doc_id=doc.id)\n                    continue\n                # keep empty documents\n                final_docs.append(doc)\n                logger.warning(\n                    \"Document ID {doc_id} has an empty content. Keeping this document as per configuration.\",\n                    doc_id=doc.id,","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/preprocessors/markdown_header_splitter.py#L347-L383","documentation":"MarkdownHeaderSplitter.run() validates that each input Document has non-None content, since it can only split textual markdown. A Document with content=None (e.g. created from a file path, binary source, or an upstream component that failed to extract text) raises this ValueError.","triggerScenarios":"Running the splitter on a pipeline where an upstream converter produced Documents with content=None (failed extraction, binary file, multimodal/document-file Documents) and passing them via documents=[...].","commonSituations":"Piping PDF/Image converter output directly into the markdown splitter, a converter silently failing and emitting an empty-content Document, or manually constructing Document(content=None, meta={...}).","solutions":["Filter documents before running: docs = [d for d in documents if d.content is not None].","Fix the upstream converter so it produces str content (check file paths, encoding, conversion logs).","Only connect text-producing components (TextFileToDocument, markdown sources) into MarkdownHeaderSplitter.","Wrap run() in try/except ValueError to skip or log documents with missing content."],"exampleFix":"// before\nsplitter.run(documents=converted_docs)  # some docs have content=None\n// after\ntext_docs = [d for d in converted_docs if isinstance(d.content, str)]\nsplitter.run(documents=text_docs)","handlingStrategy":"try-catch","validationCode":"text_docs = [d for d in documents if d.content is not None]\nsplitter.run(documents=text_docs)","typeGuard":"def is_text_document(doc) -> bool:\n    return doc.content is not None and isinstance(doc.content, str)","tryCatchPattern":"try:\n    result = splitter.run(documents=documents)\nexcept ValueError as e:\n    if \"content for document ID\" in str(e):\n        logging.warning(\"Skipping non-text documents: %s\", e)\n        result = splitter.run(documents=[d for d in documents if isinstance(d.content, str)])\n    else:\n        raise","preventionTips":["Filter out content=None documents upstream of any text splitter.","Check converter logs for failed extractions that emit empty Documents.","Verify Document.content is a str before the splitting stage in pipeline tests."],"tags":["python","haystack","document-content","pipeline"],"backgroundTag":"null-content-document","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}