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

  1. Only include SystemMessage, UserMessage, AssistantMessage, and ToolResponseMessage in the Prompt
  2. Inspect the offending message type in the error text and convert it to a supported type before the call
  3. 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

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


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/09ad2bde5a1b5fea. Report an issue: GitHub.