spring-projects/spring-ai · error · java.lang.IllegalArgumentException
Unsupported message type:
Error message
Unsupported message type:
What it means
DeepSeekChatModel.createRequest maps Spring AI Message objects to DeepSeek ChatCompletionMessages. It supports SYSTEM, USER, ASSISTANT, and TOOL (via tool-converted history) types; any other MessageType encountered is rejected with IllegalArgumentException naming the unsupported type.
Source
Thrown at models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java:385
}
String text = assistantMessage.getText();
Assert.state(text != null, "text must not be null");
return List.of(new ChatCompletionMessage(text, ChatCompletionMessage.Role.ASSISTANT, null, null,
toolCalls, isPrefixAssistantMessage, reasoningContent));
}
else if (message.getMessageType() == MessageType.TOOL) {
ToolResponseMessage toolMessage = (ToolResponseMessage) message;
toolMessage.getResponses()
.forEach(response -> Assert.isTrue(response.id() != null, "ToolResponseMessage must have an id"));
return toolMessage.getResponses()
.stream()
.map(tr -> new ChatCompletionMessage(tr.responseData(), ChatCompletionMessage.Role.TOOL, tr.name(),
tr.id(), null))
.toList();
}
else {
throw new IllegalArgumentException("Unsupported message type: " + message.getMessageType());
}
}).flatMap(List::stream).toList();
ChatCompletionRequest.Builder requestBuilder = ChatCompletionRequest.builder()
.messages(chatCompletionMessages)
.stream(stream);
DeepSeekChatOptions options = (DeepSeekChatOptions) prompt.getOptions();
Assert.state(options != null, "requestOptions must not be null");
validateThinkingParameters(options);
if (options.getModel() != null) {
requestBuilder.model(options.getModel());
}
if (options.getFrequencyPenalty() != null) {
requestBuilder.frequencyPenalty(options.getFrequencyPenalty());
}View on GitHub (pinned to 98a7beda4f)
Solutions
- Only include SystemMessage, UserMessage, AssistantMessage, and ToolResponseMessage in the Prompt
- Inspect the offending message type in the error text and convert it to a supported type before the call
- Upgrade or patch the DeepSeek module if a newer Spring AI message type must be supported
Example fix
// before messages.add(myCustomMessage); // unknown MessageType model.call(new Prompt(messages)); // throws // after messages.add(new UserMessage(myCustomMessage.getText())); model.call(new Prompt(messages));
Defensive patterns
Strategy: validation
Validate before calling
Set<MessageType> allowed = Set.of(MessageType.SYSTEM, MessageType.USER, MessageType.ASSISTANT, MessageType.TOOL); boolean valid = prompt.getInstructions().stream().allMatch(m -> allowed.contains(m.getMessageType()));
Type guard
boolean isSupportedType(Message m) { return EnumSet.of(MessageType.SYSTEM, MessageType.USER, MessageType.ASSISTANT, MessageType.TOOL).contains(m.getMessageType()); } Try / catch
try { model.call(prompt); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unsupported message type")) { /* sanitize prompt messages */ } throw e; } Prevention
- Build DeepSeek prompts only from the four supported message types
- Don't mix messages from other providers' adapters
- Re-check message type handling after Spring AI upgrades
When it happens
Trigger: Building a Prompt containing a Message whose getMessageType() is not one of SYSTEM/USER/ASSISTANT/TOOL — e.g. a custom Message implementation or a message type introduced by other Spring AI modules — then calling model.call()/stream(), which routes through createRequest.
Common situations: Mixing messages from other model adapters into a DeepSeek prompt; custom Message subclasses; framework version drift introducing new message types not yet handled by the DeepSeek adapter.
Related errors
- Unsupported message type:
- Unsupported message type:
- %s messages are not supported
- Gemini doesn't support message type:
- Unsupported message type: %s
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/09ad2bde5a1b5fea.
Report an issue: GitHub.