{"record":{"id":"8e6383d276284d21","repo":"spring-projects/spring-ai","slug":"mongochatmemoryrepository-does-not-support-tool-ca","errorCode":null,"errorMessage":"MongoChatMemoryRepository does not support tool call messages. Some messages were filtered out for conversation: + conversationId","messagePattern":"MongoChatMemoryRepository does not support tool call messages\\. Some messages were filtered out for conversation: \\+ conversationId","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"memory-repositories/spring-ai-model-chat-memory-repository-mongodb/src/main/java/org/springframework/ai/chat/memory/repository/mongo/MongoChatMemoryRepository.java","lineNumber":75,"sourceCode":"\t\treturn this.mongoTemplate.query(Conversation.class).distinct(\"conversationId\").as(String.class).all();\n\t}\n\n\t@Override\n\tpublic List<Message> findByConversationId(String conversationId) {\n\t\tvar messages = this.mongoTemplate.query(Conversation.class)\n\t\t\t.matching(Query.query(Criteria.where(\"conversationId\").is(conversationId))\n\t\t\t\t.with(Sort.by(\"timestamp\").ascending()));\n\t\treturn messages.stream().map(MongoChatMemoryRepository::mapMessage).filter(Objects::nonNull).toList();\n\t}\n\n\t@Override\n\tpublic void saveAll(String conversationId, List<Message> messages) {\n\t\tList<Message> persistableMessages = messages.stream()\n\t\t\t.filter(m -> !(m instanceof ToolResponseMessage)\n\t\t\t\t\t&& !(m instanceof AssistantMessage am && am.hasToolCalls()))\n\t\t\t.toList();\n\t\tif (logger.isWarnEnabled() && persistableMessages.size() < messages.size()) {\n\t\t\tlogger.warn(\n\t\t\t\t\t\"MongoChatMemoryRepository does not support tool call messages. Some messages were filtered out for conversation: \"\n\t\t\t\t\t\t\t+ conversationId);\n\t\t}\n\t\tdeleteByConversationId(conversationId);\n\t\tvar conversations = persistableMessages.stream()\n\t\t\t.map(message -> new Conversation(conversationId,\n\t\t\t\t\tnew Conversation.Message(message.getText(), message.getMessageType().name(), message.getMetadata()),\n\t\t\t\t\tInstant.now()))\n\t\t\t.toList();\n\t\tthis.mongoTemplate.insert(conversations, Conversation.class);\n\t}\n\n\t@Override\n\tpublic void deleteByConversationId(String conversationId) {\n\t\tthis.mongoTemplate.remove(Query.query(Criteria.where(\"conversationId\").is(conversationId)), Conversation.class);\n\t}\n\n\tpublic static @Nullable Message mapMessage(Conversation conversation) {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/memory-repositories/spring-ai-model-chat-memory-repository-mongodb/src/main/java/org/springframework/ai/chat/memory/repository/mongo/MongoChatMemoryRepository.java#L57-L93","documentation":"MongoChatMemoryRepository.saveAll() filters out ToolResponseMessage and tool-calling AssistantMessage objects because tool-call messages are not persisted in MongoDB, logging this warning when any were dropped. The conversation is then rewritten (delete + insert) without the tool-call history.","triggerScenarios":"Calling saveAll (directly or via addAndGet) with a message list that contains ToolResponseMessage or AssistantMessage.hasToolCalls() for the given conversationId.","commonSituations":"Agents using function/tool calling with MongoDB-backed ChatMemory; moving from in-memory memory (tool messages retained) to Mongo and losing tool context; conversations appearing shorter or lacking tool results after reload.","solutions":["Filter tool-call messages yourself before calling the repository so the behavior is explicit and warning-free","If tool history is essential, use a memory store that persists tool messages (in-memory, or a custom repository)","Persist tool-call exchanges to a separate Mongo collection yourself and rehydrate them when building the prompt","Upgrade spring-ai and check release notes — tool-call persistence support has been added progressively across repositories"],"exampleFix":"// before\nchatMemory.add(conversationId, toolResponseMessage); // dropped, warning logged\n\n// after\nif (!(msg instanceof ToolResponseMessage)\n        && !(msg instanceof AssistantMessage am && am.hasToolCalls())) {\n    chatMemory.add(conversationId, msg);\n} else {\n    toolCallArchive.insert(conversationId, msg); // custom persistence\n}","handlingStrategy":"validation","validationCode":"boolean persistable(Message m) {\n    return !(m instanceof ToolResponseMessage)\n        && !(m instanceof AssistantMessage am && am.hasToolCalls());\n}","typeGuard":"static boolean isToolCallMessage(Message m) {\n    return m instanceof ToolResponseMessage\n        || (m instanceof AssistantMessage am && am.hasToolCalls());\n}","tryCatchPattern":null,"preventionTips":["Filter tool messages before calling Mongo-backed chat memory","Archive tool calls to a dedicated Mongo collection if history is needed","Add a round-trip test: save messages with tools, reload, assert expectations","Check spring-ai release notes for added tool-call persistence before working around it"],"tags":["mongodb","chat-memory","tool-calls","message-filtering"],"backgroundTag":"unsupported-operation","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}