deepset-ai/haystack · error · ValueError

top_k must not be negative.

Error message

top_k must not be negative.

What it means

AnswerJoiner.run raises ValueError when a runtime `top_k` argument is negative. top_k limits how many answers are kept after joining; a negative count is meaningless, so the component rejects it before slicing. (The init-level top_k must be positive or None; runtime top_k must be >= 0 or None.)

Source

Thrown at haystack/components/joiners/answer_joiner.py:149

            - `answers`: Merged list of Answers

        :raises ValueError:
            If `top_k` is negative.
        """
        answers_list = list(answers)
        join_function = self.join_mode_function
        output_answers: list[AnswerType] = join_function(answers_list)

        if self.sort_by_score:
            output_answers = sorted(
                output_answers,
                key=lambda answer: score if (score := getattr(answer, "score", None)) is not None else -inf,
                reverse=True,
            )

        if top_k is not None:
            if top_k < 0:
                raise ValueError("top_k must not be negative.")
            output_answers = output_answers[:top_k]
        elif self.top_k is not None:
            output_answers = output_answers[: self.top_k]
        return {"answers": output_answers}

    def _concatenate(self, answer_lists: list[list[AnswerType]]) -> list[AnswerType]:
        """
        Concatenate multiple lists of Answers, flattening them into a single list.

        :param answer_lists: List of lists of Answers to be flattened.
        """
        return list(itertools.chain.from_iterable(answer_lists))

    def to_dict(self) -> dict[str, Any]:
        """
        Serializes the component to a dictionary.

        :returns:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Pass top_k=None in run() to keep all answers or fall back to the init-time top_k.
  2. Ensure the runtime top_k is >= 0 before calling run().
  3. Clamp or validate user/config-provided values: max(0, top_k).

Example fix

// before
joiner.run(answers=answers, top_k=-1)
// after
joiner.run(answers=answers, top_k=None)  # or top_k=0/positive int
Defensive patterns

Strategy: validation

Validate before calling

if run_top_k is not None and run_top_k < 0:
    raise ValueError(f"top_k must be >= 0 or None, got {run_top_k}")
answer_joiner.run(answers=answers, top_k=run_top_k)

Type guard

def is_valid_top_k(v: int | None) -> bool:
    return v is None or (isinstance(v, int) and v >= 0)

Try / catch

try:
    result = answer_joiner.run(answers=answers, top_k=k)
except ValueError as e:
    logger.warning("invalid top_k: %s", e)
    result = answer_joiner.run(answers=answers, top_k=None)

Prevention

When it happens

Trigger: Calling AnswerJoiner.run(answers=..., top_k=-1) (or any negative int) instead of passing None to disable truncation.

Common situations: Passing a sentinel value like -1 to mean 'no limit' or 'use default'; computing top_k from a config or user input where a negative value slips through; mixing up the convention (init rejects <=0, run rejects <0).

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


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