{"record":{"id":"eafafdcec03117d2","repo":"deepset-ai/haystack","slug":"pass-either-responses-or-response-fn-not-both","errorCode":null,"errorMessage":"Pass either 'responses' or 'response_fn', not both.","messagePattern":"Pass either 'responses' or 'response_fn', not both\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"haystack/components/generators/chat/mock.py","lineNumber":128,"sourceCode":"            every call), or a non-empty list of strings and/or `ChatMessage` objects that are returned in order,\n            cycling back to the start once exhausted. Strings are wrapped into assistant `ChatMessage` objects, and any\n            `ChatMessage` passed must have the `assistant` role. Mutually exclusive with `response_fn`. If neither is\n            provided, the component echoes the last message with text content.\n        :param response_fn: An optional callable that returns the reply as a string or an assistant `ChatMessage`. It\n            receives the input messages; if it accepts a second positional argument, it also receives the `tools`\n            passed to `run` (a `ToolsType` or `None`), letting the reply depend on the runtime tool schema. Use this\n            for input-dependent responses. Mutually exclusive with `responses`. To support serialization, pass a named\n            function (lambdas and nested functions cannot be serialized).\n        :param model: The model name reported in the response metadata. Purely cosmetic; no model is loaded.\n        :param meta: Additional metadata merged into the `meta` of every returned `ChatMessage`. A per-response\n            `ChatMessage`'s own metadata takes precedence over this value.\n        :param streaming_callback: An optional callback invoked with `StreamingChunk` objects reconstructed from the\n            predefined response. It lets the mock exercise streaming code paths without a real model.\n        :raises ValueError: If both `responses` and `response_fn` are provided, if `responses` is an empty list, or if\n            a `ChatMessage` response does not have the `assistant` role.\n        \"\"\"\n        if responses is not None and response_fn is not None:\n            raise ValueError(\"Pass either 'responses' or 'response_fn', not both.\")\n\n        self._responses = self._normalize_responses(responses)\n        self.response_fn = response_fn\n        self._response_fn_wants_tools = response_fn is not None and self._response_fn_accepts_tools(response_fn)\n        self.model = model\n        self.meta = meta or {}\n        self.streaming_callback = streaming_callback\n        self._call_count = 0\n        self._is_warmed_up = False\n\n    @staticmethod\n    def _normalize_responses(\n        responses: str | ChatMessage | Sequence[str | ChatMessage] | None,\n    ) -> list[ChatMessage] | None:\n        \"\"\"Normalize the `responses` argument into a non-empty list of `ChatMessage`, or `None` for echo mode.\"\"\"\n        if responses is None:\n            return None\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/generators/chat/mock.py#L110-L146","documentation":"MockChatGenerator can produce replies either from a canned list (`responses`) or from a callback (`response_fn`), but not both, since the source of replies would be ambiguous. Passing both raises ValueError in __init__.","triggerScenarios":"`MockChatGenerator(responses=[...], response_fn=my_fn)` — providing both arguments in the same call, e.g. when merging defaults and overrides in test setup.","commonSituations":"Test fixtures that set a global default response_fn and then also pass canned responses; copying an example and adding a second response source; programmatic config merging both keys.","solutions":["Provide only `responses` for canned replies","Provide only `response_fn` for dynamic replies; move canned logic into the function if needed","Check that config/fixture merging doesn't inject a default response_fn","If you want a canned default with dynamic fallback, wrap both in a single response_fn"],"exampleFix":"// before\nmock = MockChatGenerator(responses=[\"hi\"], response_fn=fn)\n// after\nmock = MockChatGenerator(responses=[\"hi\"])","handlingStrategy":"validation","validationCode":"assert not (responses is not None and response_fn is not None), \"pass either responses or response_fn\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one response strategy per mock; centralize fixture defaults","When merging configs, let explicit keys override defaults rather than accumulate","Keep canned replies inside response_fn if dynamic selection is needed"],"tags":["mock","validation","conflicting-arguments","testing"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}