spring-projects/spring-ai · warning

Unknown message type: + type

Error message

Unknown message type: + type

What it means

While deserializing stored messages in RedisChatMemoryRepository.get(), the code switches on a persisted 'type' field to rebuild AssistantMessage/SystemMessage/UserMessage/ToolResponseMessage. If the stored type string matches none of the known kinds it logs this warning and simply skips the message — it is not added to the returned list, so messages can silently disappear.

Source

Thrown at memory-repositories/spring-ai-model-chat-memory-repository-redis/src/main/java/org/springframework/ai/chat/memory/repository/redis/RedisChatMemoryRepository.java:355

						JsonArray responseArray = json.getAsJsonArray("toolResponses");
						for (JsonElement responseElement : responseArray) {
							JsonObject responseJson = responseElement.getAsJsonObject();

							String id = responseJson.has("id") ? responseJson.get("id").getAsString() : "";
							String name = responseJson.has("name") ? responseJson.get("name").getAsString() : "";
							String responseData = responseJson.has("responseData")
									? responseJson.get("responseData").getAsString() : "";

							toolResponses.add(new ToolResponseMessage.ToolResponse(id, name, responseData));
						}
					}

					messages.add(ToolResponseMessage.builder().responses(toolResponses).metadata(metadata).build());
				}
				// Add handling for other message types if needed
				else {
					if (logger.isWarnEnabled()) {
						logger.warn("Unknown message type: " + type);
					}
				}
			}
		});

		if (logger.isDebugEnabled()) {
			logger.debug("Returning " + messages.size() + " messages for conversation " + conversationId);
			messages.forEach(message -> logger.debug("Message type: " + message.getMessageType() + ", content: "
					+ message.getText() + ", class: " + message.getClass().getSimpleName()));
		}

		return messages;
	}

	public void clear(String conversationId) {
		Assert.notNull(conversationId, "Conversation ID must not be null");

		// Use QueryBuilders to create a tag field query

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Inspect the offending Redis entries (keys under the conversation) and check their 'type' field values
  2. Align writer and reader to the same Spring AI version so type tags match
  3. Migrate or delete legacy entries with unknown types (e.g. rewrite them as user/assistant messages)
  4. If you intentionally store custom types, extend/deserialize them before calling the repository
  5. Back up and clear the affected conversationId key if the data is stale

Example fix

// before
// stored: {"type":"function_call", ...}  -> message silently dropped
// after
// migrate in Redis:
// HSET/JSON.SET ... type -> "tool" (or delete the legacy entry)
// then repository.get(conversationId) returns all messages
Defensive patterns

Strategy: validation

Validate before calling

Set<String> known = Set.of("user","assistant","system","tool");
for (Object o : storedMessages) {
    String t = extractType(o);
    if (!known.contains(t)) throw new IllegalStateException("Unknown stored message type: " + t);
}

Type guard

static boolean isKnownMessageType(String type) {
    return type != null && Set.of("user","assistant","system","tool").contains(type.toLowerCase());
}

Try / catch

try { List<Message> msgs = repository.get(conversationId); }
catch (Exception e) { /* log */ }
// plus reconcile count: if msgs.size() < storedCount, some entries had unknown types

Prevention

When it happens

Trigger: Reading a conversation whose stored message entries contain a 'type' value outside {user, assistant, system, tool} — e.g. data written by an older/newer library version, hand-seeded Redis data, or corrupted/mistyped JSON.

Common situations: Spring AI version upgrade or downgrade changing the Message type taxonomy; data written by a custom serializer; manual edits to Redis JSON; messages written by another application sharing the same keyspace.

Related errors


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