{"record":{"id":"6bc941f202f6f55d","repo":"spring-projects/spring-ai","slug":"unsupported-assistant-message-class","errorCode":null,"errorMessage":"Unsupported assistant message class: ","messagePattern":"Unsupported assistant message class: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatModel.java","lineNumber":459,"sourceCode":"\t}\n\n\tprivate ChatCompletionMessage createToolChatCompletionMessage(ToolResponseMessage.ToolResponse toolResponse) {\n\t\treturn new ChatCompletionMessage(toolResponse.responseData(), ChatCompletionMessage.Role.TOOL,\n\t\t\t\ttoolResponse.name(), null, toolResponse.id());\n\t}\n\n\tprivate ChatCompletionMessage createAssistantChatCompletionMessage(Message message) {\n\t\tif (message instanceof AssistantMessage assistantMessage) {\n\t\t\tList<ToolCall> toolCalls = null;\n\n\t\t\tif (!CollectionUtils.isEmpty(assistantMessage.getToolCalls())) {\n\t\t\t\ttoolCalls = assistantMessage.getToolCalls().stream().map(this::mapToolCall).toList();\n\t\t\t}\n\t\t\tString content = assistantMessage.getText();\n\t\t\treturn new ChatCompletionMessage(content, ChatCompletionMessage.Role.ASSISTANT, null, toolCalls, null);\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\"Unsupported assistant message class: \" + message.getClass().getName());\n\t\t}\n\t}\n\n\tprivate ChatCompletionMessage createSystemChatCompletionMessage(Message message) {\n\t\tString content = message.getText();\n\t\tAssert.state(content != null, \"content must not be null\");\n\t\treturn new ChatCompletionMessage(content, ChatCompletionMessage.Role.SYSTEM);\n\t}\n\n\tprivate ChatCompletionMessage createUserChatCompletionMessage(Message message) {\n\t\tvar content = message.getText();\n\t\tAssert.state(content != null, \"content must not be null\");\n\n\t\tif (message instanceof UserMessage userMessage && !CollectionUtils.isEmpty(userMessage.getMedia())) {\n\t\t\t// @formatter:off\n\t\t\tvar contentChunks = Stream.<ChatCompletionMessage.ContentChunk>concat(\n\t\t\t\tStream.of(new ChatCompletionMessage.TextChunk(content)),\n\t\t\t\tthis.mapToImageUrlChunks(userMessage)","sourceCodeStart":441,"sourceCodeEnd":477,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatModel.java#L441-L477","documentation":"createAssistantChatCompletionMessage(Message) only accepts AssistantMessage instances; a Message with MessageType ASSISTANT of another class triggers IllegalArgumentException naming the class. The accepted subtypes (with tool calls) are handled above the throwing branch.","triggerScenarios":"A Message with MessageType ASSISTANT that is not an AssistantMessage (e.g., a custom or foreign assistant-message class) reaches the model's message mapping.","commonSituations":"Custom chat-memory or conversation-history implementations that store assistant turns as their own message class, or mixing message types from another provider integration.","solutions":["Store/replay assistant turns as AssistantMessage instances","Convert custom assistant messages via new AssistantMessage(text, Map.of(), toolCalls)","Check chat memory deserialization returns standard Spring AI message classes"],"exampleFix":"// before\nhistory.add(new MyAssistantMsg(text));\n// after\nhistory.add(new AssistantMessage(text));","handlingStrategy":"type-guard","validationCode":"if (msg.getMessageType() == MessageType.ASSISTANT && !(msg instanceof AssistantMessage)) {\n    throw new IllegalArgumentException(\"assistant messages must be AssistantMessage\");\n}","typeGuard":"boolean isAssistantMessage(Message m) {\n    return m instanceof AssistantMessage;\n}","tryCatchPattern":"try {\n    model.call(new Prompt(messages));\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unsupported assistant message class\")) {\n        logger.error(\"convert assistant message: {}\", e.getMessage());\n    } else throw e;\n}","preventionTips":["Store assistant turns as AssistantMessage in chat memory","Map history rows back to AssistantMessage on deserialization","Avoid mixing message classes from other integrations"],"tags":["mistral","assistant-message","type-mismatch","argument"],"backgroundTag":"incompatible-source-type","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}