{"record":{"id":"70def85a66c05fa7","repo":"spring-projects/spring-ai","slug":"unsupported-message-type-70def8","errorCode":null,"errorMessage":"Unsupported message type: ","messagePattern":"Unsupported message type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java","lineNumber":361,"sourceCode":"\t\t\t\t}\n\n\t\t\t\tinstructionMessages\n\t\t\t\t\t.add(Message.builder().content(contentBlocks).role(ConversationRole.ASSISTANT).build());\n\t\t\t}\n\t\t\telse if (message.getMessageType() == MessageType.TOOL) {\n\t\t\t\tList<ContentBlock> contentBlocks = new ArrayList<>(\n\t\t\t\t\t\t((ToolResponseMessage) message).getResponses().stream().map(toolResponse -> {\n\t\t\t\t\t\t\tToolResultBlock toolResultBlock = ToolResultBlock.builder()\n\t\t\t\t\t\t\t\t.toolUseId(toolResponse.id())\n\t\t\t\t\t\t\t\t.content(ToolResultContentBlock.builder().text(toolResponse.responseData()).build())\n\t\t\t\t\t\t\t\t.build();\n\t\t\t\t\t\t\treturn ContentBlock.fromToolResult(toolResultBlock);\n\t\t\t\t\t\t}).toList());\n\n\t\t\t\tinstructionMessages.add(Message.builder().content(contentBlocks).role(ConversationRole.USER).build());\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalArgumentException(\"Unsupported message type: \" + message.getMessageType());\n\t\t\t}\n\t\t}\n\n\t\t// Determine if system message caching should be applied\n\t\tboolean shouldCacheSystem = cacheOptions != null\n\t\t\t\t&& (cacheOptions.getStrategy() == BedrockCacheStrategy.SYSTEM_ONLY\n\t\t\t\t\t\t|| cacheOptions.getStrategy() == BedrockCacheStrategy.SYSTEM_AND_TOOLS);\n\n\t\tif (logger.isDebugEnabled() && cacheOptions != null) {\n\t\t\tlogger.debug(\"Cache strategy: \" + cacheOptions.getStrategy() + \", shouldCacheSystem: \" + shouldCacheSystem);\n\t\t}\n\n\t\tList<org.springframework.ai.chat.messages.Message> systemMessageList = prompt.getInstructions()\n\t\t\t.stream()\n\t\t\t.filter(m -> m.getMessageType() == MessageType.SYSTEM)\n\t\t\t.toList();\n\n\t\t// With multi-block system caching, place the cache point after the","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java#L343-L379","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nmessages.add(myCustomMessage); // MessageType not handled by Bedrock\n// after\nif (myCustomMessage.getMessageType() == MessageType.USER\n        || myCustomMessage.getMessageType() == MessageType.ASSISTANT) {\n    messages.add(myCustomMessage);\n} else {\n    messages.add(new UserMessage(myCustomMessage.getText()));\n}","handlingStrategy":"type-guard","validationCode":"static Set<MessageType> SUPPORTED = Set.of(MessageType.USER, MessageType.ASSISTANT, MessageType.SYSTEM, MessageType.TOOL);\nstatic boolean isBedrockSupported(Message m) {\n    return m != null && SUPPORTED.contains(m.getMessageType());\n}","typeGuard":"static Optional<MessageType> bedrockMessageType(Message m) {\n    return Optional.ofNullable(m).map(Message::getMessageType)\n        .filter(t -> t == MessageType.USER || t == MessageType.ASSISTANT\n            || t == MessageType.SYSTEM || t == MessageType.TOOL);\n}","tryCatchPattern":"try {\n    return bedrockModel.call(prompt);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unsupported message type\")) {\n        log.error(\"Message with unhandled type in prompt: {}\", e.getMessage());\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["bedrock","message-conversion","argument-validation"],"backgroundTag":"unsupported-enum-value","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}