deepset-ai/haystack · error

Pass either 'responses' or 'response_fn', not both.

Error message

Pass either 'responses' or 'response_fn', not both.

What it means

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__.

Source

Thrown at haystack/components/generators/chat/mock.py:128

            every call), or a non-empty list of strings and/or `ChatMessage` objects that are returned in order,
            cycling back to the start once exhausted. Strings are wrapped into assistant `ChatMessage` objects, and any
            `ChatMessage` passed must have the `assistant` role. Mutually exclusive with `response_fn`. If neither is
            provided, the component echoes the last message with text content.
        :param response_fn: An optional callable that returns the reply as a string or an assistant `ChatMessage`. It
            receives the input messages; if it accepts a second positional argument, it also receives the `tools`
            passed to `run` (a `ToolsType` or `None`), letting the reply depend on the runtime tool schema. Use this
            for input-dependent responses. Mutually exclusive with `responses`. To support serialization, pass a named
            function (lambdas and nested functions cannot be serialized).
        :param model: The model name reported in the response metadata. Purely cosmetic; no model is loaded.
        :param meta: Additional metadata merged into the `meta` of every returned `ChatMessage`. A per-response
            `ChatMessage`'s own metadata takes precedence over this value.
        :param streaming_callback: An optional callback invoked with `StreamingChunk` objects reconstructed from the
            predefined response. It lets the mock exercise streaming code paths without a real model.
        :raises ValueError: If both `responses` and `response_fn` are provided, if `responses` is an empty list, or if
            a `ChatMessage` response does not have the `assistant` role.
        """
        if responses is not None and response_fn is not None:
            raise ValueError("Pass either 'responses' or 'response_fn', not both.")

        self._responses = self._normalize_responses(responses)
        self.response_fn = response_fn
        self._response_fn_wants_tools = response_fn is not None and self._response_fn_accepts_tools(response_fn)
        self.model = model
        self.meta = meta or {}
        self.streaming_callback = streaming_callback
        self._call_count = 0
        self._is_warmed_up = False

    @staticmethod
    def _normalize_responses(
        responses: str | ChatMessage | Sequence[str | ChatMessage] | None,
    ) -> list[ChatMessage] | None:
        """Normalize the `responses` argument into a non-empty list of `ChatMessage`, or `None` for echo mode."""
        if responses is None:
            return None

View on GitHub (pinned to e318778c9b)

Solutions

  1. Provide only `responses` for canned replies
  2. Provide only `response_fn` for dynamic replies; move canned logic into the function if needed
  3. Check that config/fixture merging doesn't inject a default response_fn
  4. If you want a canned default with dynamic fallback, wrap both in a single response_fn

Example fix

// before
mock = MockChatGenerator(responses=["hi"], response_fn=fn)
// after
mock = MockChatGenerator(responses=["hi"])
Defensive patterns

Strategy: validation

Validate before calling

assert not (responses is not None and response_fn is not None), "pass either responses or response_fn"

Prevention

When it happens

Trigger: `MockChatGenerator(responses=[...], response_fn=my_fn)` — providing both arguments in the same call, e.g. when merging defaults and overrides in test setup.

Common situations: 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.

Related errors


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