deepset-ai/haystack · error · ValueError
top_k must be > 0, but got {top_k}
Error message
top_k must be > 0, but got {top_k} What it means
LostInTheMiddleRanker's __init__ rejects a top_k that is an int <= 0. top_k caps how many documents the ranker returns, so zero or negative values cannot produce a valid result set. Raised as ValueError at construction time.
Source
Thrown at haystack/components/rankers/lost_in_the_middle.py:57
def __init__(self, word_count_threshold: int | None = None, top_k: int | None = None) -> None:
"""
Initialize the LostInTheMiddleRanker.
If 'word_count_threshold' is specified, this ranker includes all documents up until the point where adding
another document would exceed the 'word_count_threshold'. The last document that causes the threshold to
be breached will be included in the resulting list of documents, but all subsequent documents will be
discarded.
:param word_count_threshold: The maximum total number of words across all documents selected by the ranker.
:param top_k: The maximum number of documents to return.
"""
if isinstance(word_count_threshold, int) and word_count_threshold <= 0:
raise ValueError(
f"Invalid value for word_count_threshold: {word_count_threshold}. word_count_threshold must be > 0."
)
if isinstance(top_k, int) and top_k <= 0:
raise ValueError(f"top_k must be > 0, but got {top_k}")
self.word_count_threshold = word_count_threshold
self.top_k = top_k
@component.output_types(documents=list[Document])
def run(
self, documents: list[Document], top_k: int | None = None, word_count_threshold: int | None = None
) -> dict[str, list[Document]]:
"""
Reranks documents based on the "lost in the middle" order.
Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
if a score is present.
:param documents: List of Documents to reorder.
:param top_k: The maximum number of documents to return.
:param word_count_threshold: The maximum total number of words across all documents selected by the ranker.
:returns:View on GitHub (pinned to e318778c9b)
Solutions
- Pass a positive integer for top_k, e.g. LostInTheMiddleRanker(top_k=10).
- Guard the source variable: only construct the ranker when top_k > 0.
- Use the default top_k by omitting the parameter if no explicit limit is needed.
Example fix
// before ranker = LostInTheMiddleRanker(top_k=0) // after ranker = LostInTheMiddleRanker(top_k=10)
Defensive patterns
Strategy: validation
Validate before calling
def ensure_valid_top_k(v):
if isinstance(v, int) and v <= 0:
raise ValueError(f"top_k must be > 0, got {v}")
return v Type guard
def is_positive_int(v) -> bool:
return isinstance(v, int) and v > 0 Try / catch
try:
ranker = LostInTheMiddleRanker(top_k=k)
except ValueError:
ranker = LostInTheMiddleRanker(top_k=10) # safe default Prevention
- Compute top_k defensively: max(1, computed_k).
- Never derive top_k from len() of a possibly empty list without a guard.
- Centralize top_k validation in a shared helper for all rankers.
When it happens
Trigger: Calling LostInTheMiddleRanker(top_k=0) or a negative int; the check only applies when the value is an int instance (None or floats bypass it).
Common situations: top_k computed from a variable (e.g. user input or len() of an empty list) that is 0; config templates with 0 placeholders; off-by-one in subtraction logic.
Understand the failure class
Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.
Related errors
- Invalid value for word_count_threshold: {word_count_threshol
- header_split_levels must be a non-empty list.
- min_effective_lines must be at least 1.
- max_effective_lines must be at least 1.
- expected_chars_per_line must be at least 1.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/77125e6712a7f22e.
Report an issue: GitHub.