deepset-ai/haystack · error · TypeError

MarkdownHeaderSplitter only works with text documents (str c

Error message

MarkdownHeaderSplitter only works with text documents (str content).

What it means

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.

Source

Thrown at haystack/components/preprocessors/markdown_header_splitter.py:370

            - `documents`: List of documents with the split texts. Each document includes:
                - A metadata field `source_id` to track the original document.
                - A metadata field `page_number` to track the original page number.
                - A metadata field `split_id` to identify the split chunk index within its parent document.
                - All other metadata copied from the original document.
        :raises ValueError: If a document has `None` content.
        :raises TypeError: If a document's content is not a string.
        """
        if self.secondary_split and not self._is_warmed_up:
            self.warm_up()
        # validate input documents
        for doc in documents:
            if doc.content is None:
                raise ValueError(
                    "MarkdownHeaderSplitter only works with text documents but content for document ID"
                    f" {doc.id} is None."
                )
            if not isinstance(doc.content, str):
                raise TypeError("MarkdownHeaderSplitter only works with text documents (str content).")

        final_docs = []
        for doc in documents:
            # handle empty documents
            if not doc.content or not doc.content.strip():  # avoid counting whitespace as content
                if self.skip_empty_documents:
                    logger.warning("Document ID {doc_id} has an empty content. Skipping this document.", doc_id=doc.id)
                    continue
                # keep empty documents
                final_docs.append(doc)
                logger.warning(
                    "Document ID {doc_id} has an empty content. Keeping this document as per configuration.",
                    doc_id=doc.id,
                )
                continue

            # split this document by headers
            header_split_docs = self._split_documents_by_markdown_headers([doc])

View on GitHub (pinned to e318778c9b)

Solutions

  1. Decode bytes to str before creating the Document: Document(content=raw.decode('utf-8')).
  2. Ensure upstream converters emit str content; inspect Document.content types before the splitter.
  3. Filter non-str documents: docs = [d for d in documents if isinstance(d.content, str)].
  4. Wrap run() in try/except TypeError when documents come from an untrusted source.

Example fix

// before
Document(content=open('doc.md', 'rb').read())  # bytes
// after
Document(content=open('doc.md', encoding='utf-8').read())  # str
Defensive patterns

Strategy: type-guard

Validate before calling

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]

Type guard

def has_str_content(doc) -> bool:
    return isinstance(doc.content, str)

Try / catch

try:
    result = splitter.run(documents=documents)
except TypeError as e:
    if "str content" in str(e):
        documents = [d for d in documents if isinstance(d.content, str)]
        result = splitter.run(documents=documents)
    else:
        raise

Prevention

When it happens

Trigger: Passing Documents whose content is bytes (binary read), a dict (from custom serialization), or another non-str type into run(documents=[...]).

Common situations: Reading files in binary mode upstream, custom converters populating content with structured data, or mixing multimodal Documents into a text-only splitting stage.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/e75f5ade3312b188. Report an issue: GitHub.