deepset-ai/haystack · error · ValueError

Some provided documents are not textual; LostInTheMiddleRank

Error message

Some provided documents are not textual; LostInTheMiddleRanker can process only text.

What it means

run() raises ValueError when any document to reorder has content=None, because LostInTheMiddleRanker can only operate on textual Documents. This check happens only when there is more than one document (single-document input returns as-is). The ranker reorders text and cannot handle empty or non-textual documents.

Source

Thrown at haystack/components/rankers/lost_in_the_middle.py:104

        if isinstance(top_k, int) and top_k <= 0:
            raise ValueError(f"top_k must be > 0, but got {top_k}")

        if not documents:
            return {"documents": []}

        top_k = top_k or self.top_k
        word_count_threshold = word_count_threshold or self.word_count_threshold

        deduplicated_documents = _deduplicate_documents(documents)
        documents_to_reorder = deduplicated_documents[:top_k] if top_k else deduplicated_documents

        # If there's only one document, return it as is
        if len(documents_to_reorder) == 1:
            return {"documents": documents_to_reorder}

        # Raise an error if any document is not textual
        if any(doc.content is None for doc in documents_to_reorder):
            raise ValueError("Some provided documents are not textual; LostInTheMiddleRanker can process only text.")

        # Initialize word count and indices for the "lost in the middle" order
        word_count = 0
        document_index = list(range(len(documents_to_reorder)))
        lost_in_the_middle_indices = [0]

        # If word count threshold is set and the first document has content, calculate word count for the first document
        if word_count_threshold and documents_to_reorder[0].content:
            word_count = len(documents_to_reorder[0].content.split())

            # If the first document already meets the word count threshold, return it
            if word_count >= word_count_threshold:
                return {"documents": [documents_to_reorder[0]]}

        # Start from the second document and create "lost in the middle" order
        for doc_idx in document_index[1:]:
            # Calculate the index at which the current document should be inserted
            insertion_index = len(lost_in_the_middle_indices) // 2 + len(lost_in_the_middle_indices) % 2

View on GitHub (pinned to e318778c9b)

Solutions

  1. Filter out Documents with None content before ranking: docs = [d for d in docs if d.content is not None].
  2. Fix the upstream component so all documents carry text content (check converter/extractor settings or file validity).
  3. Use a ranker that supports the document modality you have (e.g. multimodal rankers) instead of LostInTheMiddleRanker.

Example fix

// before
result = ranker.run(documents=all_docs)  # some have content=None
// after
text_docs = [d for d in all_docs if d.content is not None]
result = ranker.run(documents=text_docs)
Defensive patterns

Strategy: type-guard

Validate before calling

non_text = [d.id for d in docs if d.content is None]
if non_text:
    raise ValueError(f"Documents without text content: {non_text}")

Type guard

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

Try / catch

try:
    result = ranker.run(documents=docs)
except ValueError:
    docs = [d for d in docs if d.content is not None]
    result = ranker.run(documents=docs)

Prevention

When it happens

Trigger: Passing a list of Documents where at least one has content=None (e.g. Documents built from file/image metadata, or documents with content stored only in meta/data fields) into ranker.run(documents=...) with len > 1.

Common situations: Upstream components (converters, extractors) producing Documents with content=None on failure; mixing document types (table, image, multimodal) into a text ranker; loading documents from a document store where text extraction failed.

Related errors


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