{"record":{"id":"baf2c29472959581","repo":"deepset-ai/haystack","slug":"top-k-must-not-be-negative","errorCode":null,"errorMessage":"top_k must not be negative.","messagePattern":"top_k must not be negative\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/joiners/answer_joiner.py","lineNumber":149,"sourceCode":"            - `answers`: Merged list of Answers\n\n        :raises ValueError:\n            If `top_k` is negative.\n        \"\"\"\n        answers_list = list(answers)\n        join_function = self.join_mode_function\n        output_answers: list[AnswerType] = join_function(answers_list)\n\n        if self.sort_by_score:\n            output_answers = sorted(\n                output_answers,\n                key=lambda answer: score if (score := getattr(answer, \"score\", None)) is not None else -inf,\n                reverse=True,\n            )\n\n        if top_k is not None:\n            if top_k < 0:\n                raise ValueError(\"top_k must not be negative.\")\n            output_answers = output_answers[:top_k]\n        elif self.top_k is not None:\n            output_answers = output_answers[: self.top_k]\n        return {\"answers\": output_answers}\n\n    def _concatenate(self, answer_lists: list[list[AnswerType]]) -> list[AnswerType]:\n        \"\"\"\n        Concatenate multiple lists of Answers, flattening them into a single list.\n\n        :param answer_lists: List of lists of Answers to be flattened.\n        \"\"\"\n        return list(itertools.chain.from_iterable(answer_lists))\n\n    def to_dict(self) -> dict[str, Any]:\n        \"\"\"\n        Serializes the component to a dictionary.\n\n        :returns:","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/joiners/answer_joiner.py#L131-L167","documentation":"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.)","triggerScenarios":"Calling AnswerJoiner.run(answers=..., top_k=-1) (or any negative int) instead of passing None to disable truncation.","commonSituations":"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).","solutions":["Pass top_k=None in run() to keep all answers or fall back to the init-time top_k.","Ensure the runtime top_k is >= 0 before calling run().","Clamp or validate user/config-provided values: max(0, top_k)."],"exampleFix":"// before\njoiner.run(answers=answers, top_k=-1)\n// after\njoiner.run(answers=answers, top_k=None)  # or top_k=0/positive int","handlingStrategy":"validation","validationCode":"if run_top_k is not None and run_top_k < 0:\n    raise ValueError(f\"top_k must be >= 0 or None, got {run_top_k}\")\nanswer_joiner.run(answers=answers, top_k=run_top_k)","typeGuard":"def is_valid_top_k(v: int | None) -> bool:\n    return v is None or (isinstance(v, int) and v >= 0)","tryCatchPattern":"try:\n    result = answer_joiner.run(answers=answers, top_k=k)\nexcept ValueError as e:\n    logger.warning(\"invalid top_k: %s\", e)\n    result = answer_joiner.run(answers=answers, top_k=None)","preventionTips":["Never use -1 as a 'no limit' sentinel; use None","Validate user/config-supplied top_k at the boundary","Remember run() allows 0 but init does not"],"tags":["validation","python","haystack"],"backgroundTag":"invalid-parameter-value","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}