deepset-ai/haystack · error · ValueError

MarkdownHeaderSplitter only works with text documents but co

Error message

MarkdownHeaderSplitter only works with text documents but content for document ID {doc.id} is None.

What it means

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.

Source

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

        Run the markdown header splitter with optional secondary splitting.

        :param documents: List of documents to split

        :returns: A dictionary with the following key:
            - `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,

View on GitHub (pinned to e318778c9b)

Solutions

  1. Filter documents before running: docs = [d for d in documents if d.content is not None].
  2. Fix the upstream converter so it produces str content (check file paths, encoding, conversion logs).
  3. Only connect text-producing components (TextFileToDocument, markdown sources) into MarkdownHeaderSplitter.
  4. Wrap run() in try/except ValueError to skip or log documents with missing content.

Example fix

// before
splitter.run(documents=converted_docs)  # some docs have content=None
// after
text_docs = [d for d in converted_docs if isinstance(d.content, str)]
splitter.run(documents=text_docs)
Defensive patterns

Strategy: try-catch

Validate before calling

text_docs = [d for d in documents if d.content is not None]
splitter.run(documents=text_docs)

Type guard

def is_text_document(doc) -> bool:
    return doc.content is not None and isinstance(doc.content, str)

Try / catch

try:
    result = splitter.run(documents=documents)
except ValueError as e:
    if "content for document ID" in str(e):
        logging.warning("Skipping non-text documents: %s", e)
        result = splitter.run(documents=[d for d in documents if isinstance(d.content, str)])
    else:
        raise

Prevention

When it happens

Trigger: 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=[...].

Common situations: 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={...}).

Related errors


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