deepset-ai/haystack · error · ValueError

PythonCodeSplitter only works with text documents but conten

Error message

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

What it means

PythonCodeSplitter.run() rejects documents whose content is None because it must parse and split Python source text. This documents the input contract: only text documents (str content) are supported, and the check raises before any processing happens.

Source

Thrown at haystack/components/preprocessors/python_code_splitter.py:581

    @component.output_types(documents=list[Document])
    def run(self, documents: list[Document]) -> dict[str, list[Document]]:
        """
        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

View on GitHub (pinned to e318778c9b)

Solutions

  1. Filter documents before the splitter: docs = [d for d in docs if d.content is not None].
  2. Fix the upstream converter so it never emits content=None (check file paths and extraction logic).
  3. Use DocumentSplitter for generic text if content may be non-Python; ensure only valid source docs reach this splitter.

Example fix

// before
result = splitter.run(documents=all_docs)
// after
valid = [d for d in all_docs if d.content is not None]
result = splitter.run(documents=valid)
Defensive patterns

Strategy: type-guard

Validate before calling

invalid = [d.id for d in documents if d.content is None]
if invalid:
    raise ValueError(f'Documents with None content: {invalid}')

Type guard

def has_text(doc) -> bool:
    return doc.content is not None

documents = [d for d in documents if has_text(d)]

Try / catch

try:
    result = splitter.run(documents=docs)
except ValueError as e:
    logger.error('Non-text document in input: %s', e)
    result = splitter.run(documents=[d for d in docs if d.content is not None])

Prevention

When it happens

Trigger: Running the component with documents produced by converters/extractors that failed silently and set content=None, or manually constructed Document(content=None) passed into the 'documents' input.

Common situations: Pipeline where an upstream TextFileToDocument/extractor yields empty results for binary or unreadable files; connecting a DocumentCreator that omits content; multi-format ingestion where non-Python/binary files slip in.

Related errors


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