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
- 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.
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
- 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.
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
- 'response_fn' must return a string or ChatMessage, got {type
- Unsupported tool result: {result.result}
- Invalid messages type. Expected list[ChatMessage] or str.
- MarkdownHeaderSplitter only works with text documents but co
- PythonCodeSplitter only works with text documents but conten
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/e75f5ade3312b188.
Report an issue: GitHub.