deepset-ai/haystack · error · TypeError
PythonCodeSplitter only works with text documents (str conte
Error message
PythonCodeSplitter only works with text documents (str content).
What it means
PythonCodeSplitter.run() raises TypeError when a document's content is not a str. The splitter tokenizes Python source and can only handle string content; arbitrary objects (bytes, lists, dicts) are rejected explicitly rather than failing obscurely later.
Source
Thrown at haystack/components/preprocessors/python_code_splitter.py:585
Split each Python source ``Document`` into syntax-aware chunks.
:param documents: Documents whose ``content`` is Python source code. Each
document's ``meta`` is propagated onto its chunks.
:returns: ``{"documents": [...]}`` where each chunk's meta additionally carries
``source_id``, ``split_id``, ``start_line``, ``end_line``, ``unit_kinds`` and
- where applicable - ``include_classes``, ``decorators``, ``docstrings``,
``secondary_split``.
:raises ValueError: If any document's content is ``None``.
:raises TypeError: If any document's content is not a string.
:raises SyntaxError: If a document's content is not valid Python.
"""
for doc in documents:
if doc.content is None:
raise ValueError(
f"PythonCodeSplitter only works with text documents but content for document ID {doc.id} is None."
)
if not isinstance(doc.content, str):
raise TypeError("PythonCodeSplitter only works with text documents (str content).")
final_docs: list[Document] = []
for doc in documents:
assert doc.content is not None # narrowed by the loop above
if not doc.content.strip():
logger.warning("Document ID {doc_id} has empty content. Skipping this document.", doc_id=doc.id)
continue
units = self._extract_units(doc.content)
if not units:
continue
chunks = self._merge_units(units)
split_id = 0
for chunk in chunks:
if len(chunk) == 1 and self._is_oversized(chunk[0]):
for piece in self._secondary_split(chunk[0], doc):
piece.meta["split_id"] = split_idView on GitHub (pinned to e318778c9b)
Solutions
- Decode bytes before wrapping: Document(content=data.decode('utf-8')).
- Ensure upstream components emit str content (check the converter used).
- Add an isinstance check in a custom component before emitting documents.
Example fix
// before Document(content=open(path, 'rb').read()) // after Document(content=open(path, 'r', encoding='utf-8').read())
Defensive patterns
Strategy: type-guard
Validate before calling
bad = [d.id for d in documents if not isinstance(d.content, str)]
if bad:
raise TypeError(f'Non-str content in documents: {bad}') Type guard
def is_text_document(doc) -> bool:
return isinstance(doc.content, str)
documents = [d for d in documents if is_text_document(d)] Try / catch
try:
result = splitter.run(documents=docs)
except TypeError as e:
logger.error('Non-str document content: %s', e)
result = splitter.run(documents=[d for d in docs if isinstance(d.content, str)]) Prevention
- Always open files in text mode with explicit encoding before creating Documents.
- Enforce str content in custom components before emitting.
- Type-annotate pipelines so mypy catches non-str content flows.
When it happens
Trigger: Passing documents whose content is bytes (e.g. raw file reads), a list of chunks, or any non-str object; constructing Document(content=<non-str>) manually and feeding it to run().
Common situations: Reading files in binary mode ('rb') upstream; custom components that store structured data in content; version changes after migrating from another splitter that accepted different types.
Related errors
- MarkdownHeaderSplitter only works with text documents but co
- MarkdownHeaderSplitter only works with text documents (str c
- PythonCodeSplitter only works with text documents but conten
- All separators must be strings.
- Document with ID '{doc.id}' comes from the PDF file '{resolv
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/7c0608230d3641f1.
Report an issue: GitHub.