spring-projects/spring-ai · error · IllegalArgumentException
Unsupported message type:
Error message
Unsupported message type:
What it means
BedrockProxyChatModel.createRequest maps Spring AI Message objects to Bedrock Converse API messages. Each MessageType has a known mapping (user, assistant, system, tool); when a message carries a MessageType the converter does not handle, it throws IllegalArgumentException 'Unsupported message type: ' + the type. This usually means a custom or unrecognized message subtype reached the request builder.
Source
Thrown at models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java:361
}
instructionMessages
.add(Message.builder().content(contentBlocks).role(ConversationRole.ASSISTANT).build());
}
else if (message.getMessageType() == MessageType.TOOL) {
List<ContentBlock> contentBlocks = new ArrayList<>(
((ToolResponseMessage) message).getResponses().stream().map(toolResponse -> {
ToolResultBlock toolResultBlock = ToolResultBlock.builder()
.toolUseId(toolResponse.id())
.content(ToolResultContentBlock.builder().text(toolResponse.responseData()).build())
.build();
return ContentBlock.fromToolResult(toolResultBlock);
}).toList());
instructionMessages.add(Message.builder().content(contentBlocks).role(ConversationRole.USER).build());
}
else {
throw new IllegalArgumentException("Unsupported message type: " + message.getMessageType());
}
}
// Determine if system message caching should be applied
boolean shouldCacheSystem = cacheOptions != null
&& (cacheOptions.getStrategy() == BedrockCacheStrategy.SYSTEM_ONLY
|| cacheOptions.getStrategy() == BedrockCacheStrategy.SYSTEM_AND_TOOLS);
if (logger.isDebugEnabled() && cacheOptions != null) {
logger.debug("Cache strategy: " + cacheOptions.getStrategy() + ", shouldCacheSystem: " + shouldCacheSystem);
}
List<org.springframework.ai.chat.messages.Message> systemMessageList = prompt.getInstructions()
.stream()
.filter(m -> m.getMessageType() == MessageType.SYSTEM)
.toList();
// With multi-block system caching, place the cache point after theView on GitHub (pinned to 98a7beda4f)
Solutions
- Log message.getMessageType() for all messages in the Prompt to find the offending one.
- Ensure every message is created via UserMessage, AssistantMessage, SystemMessage, or ToolResponseMessage so the type is one Bedrock supports.
- Filter/convert foreign message types before constructing the Prompt for Bedrock.
- Upgrade spring-ai-bedrock-converse if a supported type is being rejected (framework bug).
Example fix
// before
messages.add(myCustomMessage); // MessageType not handled by Bedrock
// after
if (myCustomMessage.getMessageType() == MessageType.USER
|| myCustomMessage.getMessageType() == MessageType.ASSISTANT) {
messages.add(myCustomMessage);
} else {
messages.add(new UserMessage(myCustomMessage.getText()));
} Defensive patterns
Strategy: type-guard
Validate before calling
static Set<MessageType> SUPPORTED = Set.of(MessageType.USER, MessageType.ASSISTANT, MessageType.SYSTEM, MessageType.TOOL);
static boolean isBedrockSupported(Message m) {
return m != null && SUPPORTED.contains(m.getMessageType());
} Type guard
static Optional<MessageType> bedrockMessageType(Message m) {
return Optional.ofNullable(m).map(Message::getMessageType)
.filter(t -> t == MessageType.USER || t == MessageType.ASSISTANT
|| t == MessageType.SYSTEM || t == MessageType.TOOL);
} Try / catch
try {
return bedrockModel.call(prompt);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unsupported message type")) {
log.error("Message with unhandled type in prompt: {}", e.getMessage());
}
throw e;
} Prevention
- Build prompts only from UserMessage/AssistantMessage/SystemMessage/ToolResponseMessage.
- Convert or drop messages from other model adapters before sending to Bedrock.
- Add a pre-send assertion over prompt.getMessages() types in tests.
When it happens
Trigger: Passing a Message whose getMessageType() returns a value outside the handled set into BedrockProxyChatModel.call()/stream() — e.g. a custom Message implementation, a deprecated message type, or framework messages (like function/tool callback results of an unexpected shape) constructed manually.
Common situations: Mixing messages from another model adapter into a Bedrock conversation; upgrading Spring AI where a new MessageType was introduced while code still assumes old types; hand-building Prompt messages with a wrong MessageType enum.
Related errors
- Invalid video content type:
- The region '<region>' is not a valid region!
- Required properties for TitanEmbeddingBedrockApi are missing
- InputType property for BedrockTitanEmbeddingModel is missing
- Prefix or toolName cannot be null or empty
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/70def85a66c05fa7.
Report an issue: GitHub.