spring-projects/spring-ai · error · IllegalArgumentException

Unexpected value type %s in the list!

Error message

Unexpected value type %s in the list!

What it means

During serialization of message content lists (MistralAiApi ContentChunkSerializer), each element must be a ContentChunk instance. If any element of the list is another type, IllegalArgumentException('Unexpected value type %s in the list!') is thrown to prevent writing invalid JSON to the Mistral API.

Source

Thrown at models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/api/MistralAiApi.java:1532

		}

		public static class ContentSerializer extends ValueSerializer<Object> {

			@Override
			public void serialize(Object value, JsonGenerator jsonGenerator,
					SerializationContext serializationContext) {
				if (value instanceof String text) {
					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();

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Ensure every element of the content list is a MistralAiApi.ContentChunk (wrap strings in a ContentChunk).
  2. Convert legacy String content with the library's content-chunk constructors before building the message.
  3. Audit custom message-history/memory code to guarantee the list only contains ContentChunk instances.

Example fix

// before
List<Object> content = List.of("hello"); // plain String element
// after
List<Object> content = List.of(new MistralAiApi.ContentChunk.TextChunk("hello"));
Defensive patterns

Strategy: type-guard

Validate before calling

for (Object o : contentList) {
    if (!(o instanceof MistralAiApi.ContentChunk)) {
        throw new IllegalArgumentException("Non-ContentChunk element: " + o.getClass());
    }
}

Type guard

boolean isContentChunkList(List<Object> l) { return l == null || l.stream().allMatch(o -> o instanceof MistralAiApi.ContentChunk); }

Try / catch

try {
    chatModel.call(prompt);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Unexpected value type")) { /* sanitize content list and retry once */ }
}

Prevention

When it happens

Trigger: Building a ChatMessage whose content is a List containing objects other than ContentChunk (e.g. raw Strings, Media, or custom DTOs) and sending it through MistralAiApi.

Common situations: Users upgrading Spring AI versions where message content changed from String to List<Object> and they put arbitrary objects in the list; custom ChatMemory implementations storing non-ContentChunk items.

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


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