{"record":{"id":"b8849e4e020098a7","repo":"deepset-ai/haystack","slug":"some-provided-documents-are-not-textual-lostinthe","errorCode":null,"errorMessage":"Some provided documents are not textual; LostInTheMiddleRanker can process only text.","messagePattern":"Some provided documents are not textual; LostInTheMiddleRanker can process only text\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/rankers/lost_in_the_middle.py","lineNumber":104,"sourceCode":"        if isinstance(top_k, int) and top_k <= 0:\n            raise ValueError(f\"top_k must be > 0, but got {top_k}\")\n\n        if not documents:\n            return {\"documents\": []}\n\n        top_k = top_k or self.top_k\n        word_count_threshold = word_count_threshold or self.word_count_threshold\n\n        deduplicated_documents = _deduplicate_documents(documents)\n        documents_to_reorder = deduplicated_documents[:top_k] if top_k else deduplicated_documents\n\n        # If there's only one document, return it as is\n        if len(documents_to_reorder) == 1:\n            return {\"documents\": documents_to_reorder}\n\n        # Raise an error if any document is not textual\n        if any(doc.content is None for doc in documents_to_reorder):\n            raise ValueError(\"Some provided documents are not textual; LostInTheMiddleRanker can process only text.\")\n\n        # Initialize word count and indices for the \"lost in the middle\" order\n        word_count = 0\n        document_index = list(range(len(documents_to_reorder)))\n        lost_in_the_middle_indices = [0]\n\n        # If word count threshold is set and the first document has content, calculate word count for the first document\n        if word_count_threshold and documents_to_reorder[0].content:\n            word_count = len(documents_to_reorder[0].content.split())\n\n            # If the first document already meets the word count threshold, return it\n            if word_count >= word_count_threshold:\n                return {\"documents\": [documents_to_reorder[0]]}\n\n        # Start from the second document and create \"lost in the middle\" order\n        for doc_idx in document_index[1:]:\n            # Calculate the index at which the current document should be inserted\n            insertion_index = len(lost_in_the_middle_indices) // 2 + len(lost_in_the_middle_indices) % 2","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/rankers/lost_in_the_middle.py#L86-L122","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nresult = ranker.run(documents=all_docs)  # some have content=None\n// after\ntext_docs = [d for d in all_docs if d.content is not None]\nresult = ranker.run(documents=text_docs)","handlingStrategy":"type-guard","validationCode":"non_text = [d.id for d in docs if d.content is None]\nif non_text:\n    raise ValueError(f\"Documents without text content: {non_text}\")","typeGuard":"def is_textual(doc) -> bool:\n    return doc.content is not None and isinstance(doc.content, str)","tryCatchPattern":"try:\n    result = ranker.run(documents=docs)\nexcept ValueError:\n    docs = [d for d in docs if d.content is not None]\n    result = ranker.run(documents=docs)","preventionTips":["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."],"tags":["python","ranker","documents","content-validation"],"backgroundTag":"non-textual-document","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}