{"record":{"id":"5057e9025b3e0b13","repo":"deepset-ai/haystack","slug":"each-chatmessage-response-must-have-the-assistant","errorCode":null,"errorMessage":"Each ChatMessage response must have the 'assistant' role, got '{item.role.value}'.","messagePattern":"Each ChatMessage response must have the 'assistant' role, got '(.+?)'\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"haystack/components/generators/chat/mock.py","lineNumber":164,"sourceCode":"\n        items: list[str | ChatMessage]\n        if isinstance(responses, (str, ChatMessage)):\n            items = [responses]\n        elif isinstance(responses, Sequence):\n            items = list(responses)\n        else:\n            raise TypeError(f\"'responses' must be a string, ChatMessage, or a sequence of them, got {type(responses)}.\")\n\n        if len(items) == 0:\n            raise ValueError(\"'responses' must not be an empty list.\")\n\n        normalized: list[ChatMessage] = []\n        for item in items:\n            if isinstance(item, str):\n                normalized.append(ChatMessage.from_assistant(item))\n            elif isinstance(item, ChatMessage):\n                if item.role != ChatRole.ASSISTANT:\n                    raise ValueError(\n                        f\"Each ChatMessage response must have the 'assistant' role, got '{item.role.value}'.\"\n                    )\n                normalized.append(item)\n            else:\n                raise TypeError(f\"Each response must be a string or ChatMessage, got {type(item)}.\")\n        return normalized\n\n    def to_dict(self) -> dict[str, Any]:\n        \"\"\"Serialize the component to a dictionary.\"\"\"\n        responses = [msg.to_dict() for msg in self._responses] if self._responses is not None else None\n        response_fn = serialize_callable(self.response_fn) if self.response_fn is not None else None\n        streaming_callback = serialize_callable(self.streaming_callback) if self.streaming_callback else None\n        return default_to_dict(\n            self,\n            responses=responses,\n            response_fn=response_fn,\n            model=self.model,\n            meta=self.meta,","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/generators/chat/mock.py#L146-L182","documentation":"Canned ChatMessage responses for MockChatGenerator must have the assistant role, since the mock simulates the model's reply. Passing a ChatMessage with another role (user, system, tool) raises ValueError stating the actual role found.","triggerScenarios":"`MockChatGenerator(responses=[ChatMessage.from_user(\"hi\")])` or from_system/from_tool messages in the responses list — commonly when replaying a recorded conversation where user/system messages were included.","commonSituations":"Replaying captured transcripts without filtering roles; constructing messages with the wrong factory; copying ChatMessage objects from input logs into responses.","solutions":["Convert the message: ChatMessage.from_assistant(item.text) keeping the content you need","Filter the list to assistant-role messages before constructing the mock","Use strings in `responses` (they're auto-wrapped as assistant messages)"],"exampleFix":"// before\nmock = MockChatGenerator(responses=[ChatMessage.from_user(\"hello\")])\n// after\nmock = MockChatGenerator(responses=[ChatMessage.from_assistant(\"hello\")])","handlingStrategy":"validation","validationCode":"responses = [\n    m if isinstance(m, str) or m.role == ChatRole.ASSISTANT\n    else ChatMessage.from_assistant(m.text)\n    for m in responses\n]","typeGuard":"def is_assistant_message(m: ChatMessage) -> bool:\n    return m.role == ChatRole.ASSISTANT","tryCatchPattern":null,"preventionTips":["Use plain strings for canned replies (auto-assistant)","When replaying transcripts, filter to assistant messages only","Assert roles in fixture builders"],"tags":["mock","validation","chat-message","role","testing"],"backgroundTag":"invalid-message-role","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}