spring-projects/spring-ai · error · IllegalArgumentException
Unexpected value type %s!
Error message
Unexpected value type %s!
What it means
The content serializer in MistralAiApi only knows how to serialize content values that are String or List (of ContentChunk). If the message content field holds any other type, IllegalArgumentException('Unexpected value type %s!') is thrown.
Source
Thrown at models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/api/MistralAiApi.java:1540
jsonGenerator.writeString(text);
}
else if (value instanceof List<?> list) {
jsonGenerator.writeStartArray();
for (var object : list) {
if (object instanceof ContentChunk contentChunk) {
jsonGenerator.writePOJO(contentChunk);
}
else {
throw new IllegalArgumentException(
"Unexpected value type %s in the list!".formatted(object.getClass()));
}
}
jsonGenerator.writeEndArray();
}
else {
throw new IllegalArgumentException("Unexpected value type %s!".formatted(value.getClass()));
}
}
}
public static class ContentDeserializer extends ValueDeserializer<Object> {
@Override
public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) {
var jsonToken = jsonParser.currentToken();
if (jsonToken == JsonToken.VALUE_STRING) {
return jsonParser.getValueAsString();
}
if (jsonToken == JsonToken.START_ARRAY) {
List<ContentChunk> contentChunks = new ArrayList<>();
View on GitHub (pinned to 98a7beda4f)
Solutions
- Use String or List<ContentChunk> as the message content type.
- Convert unsupported content objects (e.g. byte[] or Media) to String or ContentChunk before building the message.
- Locate the code that assigns the offending type via the class name in the error message.
Example fix
// before
new ChatUserMessage(Map.of("key", "value"), null); // unsupported content type
// after
new ChatUserMessage("hello", null); // String content Defensive patterns
Strategy: type-guard
Validate before calling
Object content = message.getContent();
if (!(content instanceof String) && !(content instanceof List<?>)) {
throw new IllegalArgumentException("Content must be String or List<ContentChunk>: " + content.getClass());
} Type guard
boolean isValidContent(Object c) { return c instanceof String || (c instanceof List<?> l && l.stream().allMatch(x -> x instanceof MistralAiApi.ContentChunk)); } Try / catch
try {
chatModel.call(prompt);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unexpected value type")) { /* convert content to String and rebuild prompt */ }
} Prevention
- Only assign String or List<ContentChunk> values to message content.
- Convert Media/byte[]/Map content to a supported representation before message construction.
- Cover message building with unit tests that serialize a sample message.
When it happens
Trigger: Setting a ChatMessage's content to an unsupported object type (e.g. a Map, byte[], or custom class) instead of String or List<ContentChunk> before calling the Mistral API.
Common situations: Custom Prompt converters or memory adapters passing arbitrary content objects; refactoring code that assumed content was always a String.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unexpected value type %s in the list!
- Unsupported tool message class:
- Unsupported assistant message class:
- Unsupported media data type:
- Parameter must be of type List<McpSchema.Prompt>:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/358525e70635976d.
Report an issue: GitHub.