{"record":{"id":"e75f5ade3312b188","repo":"deepset-ai/haystack","slug":"markdownheadersplitter-only-works-with-text-docume-e75f5a","errorCode":null,"errorMessage":"MarkdownHeaderSplitter only works with text documents (str content).","messagePattern":"MarkdownHeaderSplitter only works with text documents \\(str content\\)\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"haystack/components/preprocessors/markdown_header_splitter.py","lineNumber":370,"sourceCode":"            - `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,\n                )\n                continue\n\n            # split this document by headers\n            header_split_docs = self._split_documents_by_markdown_headers([doc])","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/preprocessors/markdown_header_splitter.py#L352-L388","documentation":"MarkdownHeaderSplitter.run() raises this TypeError when a Document's content is set but is not a str (e.g. bytes, dict, list). The component only supports markdown/plain text documents.","triggerScenarios":"Passing Documents whose content is bytes (binary read), a dict (from custom serialization), or another non-str type into run(documents=[...]).","commonSituations":"Reading files in binary mode upstream, custom converters populating content with structured data, or mixing multimodal Documents into a text-only splitting stage.","solutions":["Decode bytes to str before creating the Document: Document(content=raw.decode('utf-8')).","Ensure upstream converters emit str content; inspect Document.content types before the splitter.","Filter non-str documents: docs = [d for d in documents if isinstance(d.content, str)].","Wrap run() in try/except TypeError when documents come from an untrusted source."],"exampleFix":"// before\nDocument(content=open('doc.md', 'rb').read())  # bytes\n// after\nDocument(content=open('doc.md', encoding='utf-8').read())  # str","handlingStrategy":"type-guard","validationCode":"docs = [d if isinstance(d.content, str) else Document(content=d.content.decode('utf-8', errors='replace')) if isinstance(d.content, bytes) else d for d in documents]","typeGuard":"def has_str_content(doc) -> bool:\n    return isinstance(doc.content, str)","tryCatchPattern":"try:\n    result = splitter.run(documents=documents)\nexcept TypeError as e:\n    if \"str content\" in str(e):\n        documents = [d for d in documents if isinstance(d.content, str)]\n        result = splitter.run(documents=documents)\n    else:\n        raise","preventionTips":["Open text files in text mode (encoding='utf-8'), not 'rb'.","Keep structured data in Document.meta, never in content.","Type-check content at pipeline boundaries before splitting."],"tags":["python","haystack","type-error","document-content"],"backgroundTag":"wrong-content-type","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}