deepset-ai/haystack · error

'responses' must not be an empty list.

Error message

'responses' must not be an empty list.

What it means

MockChatGenerator requires at least one canned reply; an empty `responses` list gives the mock nothing to return, so _normalize_responses raises ValueError. Empty strings are allowed, but an empty list is not.

Source

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

    @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

        items: list[str | ChatMessage]
        if isinstance(responses, (str, ChatMessage)):
            items = [responses]
        elif isinstance(responses, Sequence):
            items = list(responses)
        else:
            raise TypeError(f"'responses' must be a string, ChatMessage, or a sequence of them, got {type(responses)}.")

        if len(items) == 0:
            raise ValueError("'responses' must not be an empty list.")

        normalized: list[ChatMessage] = []
        for item in items:
            if isinstance(item, str):
                normalized.append(ChatMessage.from_assistant(item))
            elif isinstance(item, ChatMessage):
                if item.role != ChatRole.ASSISTANT:
                    raise ValueError(
                        f"Each ChatMessage response must have the 'assistant' role, got '{item.role.value}'."
                    )
                normalized.append(item)
            else:
                raise TypeError(f"Each response must be a string or ChatMessage, got {type(item)}.")
        return normalized

    def to_dict(self) -> dict[str, Any]:
        """Serialize the component to a dictionary."""
        responses = [msg.to_dict() for msg in self._responses] if self._responses is not None else None

View on GitHub (pinned to e318778c9b)

Solutions

  1. Provide at least one response, e.g. responses=["ok"]
  2. Guard construction: fall back to a placeholder response when the list is empty
  3. If you need a generator that errors or no-ops, use response_fn instead of an empty list

Example fix

// before
mock = MockChatGenerator(responses=[])
// after
mock = MockChatGenerator(responses=["default reply"])
Defensive patterns

Strategy: validation

Validate before calling

if not responses:
    responses = ["placeholder reply"]  # or skip creating the mock

Type guard

def has_responses(r) -> bool:
    if isinstance(r, (str, ChatMessage)):
        return True
    return isinstance(r, Sequence) and len(r) > 0

Prevention

When it happens

Trigger: `MockChatGenerator(responses=[])` or passing an empty tuple/sequence, e.g. a list built by filtering that matched nothing, or a default [] in test fixtures.

Common situations: Fixtures with responses=[] as a placeholder never filled; parametrized tests with no cases; YAML/config with an empty array.

Related errors


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