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) % 2View on GitHub (pinned to e318778c9b)
Solutions
- Filter out Documents with None content before ranking: docs = [d for d in docs if d.content is not None].
- Fix the upstream component so all documents carry text content (check converter/extractor settings or file validity).
- 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
- Filter documents with content=None before every text-only ranker.
- Inspect upstream converters/extractors for documents with failed text extraction.
- Avoid mixing image/table/multimodal Documents into text-only components; a single-document input bypasses this check, so don't rely on that path.
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
- MockDocumentEmbedder expects a list of Documents as input.In
- OpenAIDocumentEmbedder expects a list of Documents as input.
- Invalid value for word_count_threshold: {word_count_threshol
- top_k must be > 0, but got {top_k}
- top_k must be > 0, but got {top_k}
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/b8849e4e020098a7.
Report an issue: GitHub.