Description
Bug description
When a ChatResponse from the model includes a ToolCall (i.e., finishReason=TOOL_CALLS), the corresponding AssistantMessage has textContent = null.
When this message is added to the JdbcChatMemoryRepository, the implementation attempts to insert it into the database without null-checking the content field. This causes a SQL integrity error due to a NOT NULL constraint on the content column.
The ToolResponseMessage (or AssistantMessage with only toolCalls and no content) is not handled correctly in JdbcChatMemoryRepository. This leads to the following exception:
java.sql.SQLIntegrityConstraintViolationException: (conn=498) Column 'content' cannot be null
In contrast, the default in-memory implementation (MessageWindowChatMemory) tolerates null content and saving such messages with null textContent.
Environment
- spring-ai 1.0.0
- mariadb:10.11
Steps to reproduce
- Use a ChatModel that returns a response containing only toolCalls (e.g., OpenAI with function/tool calling).
- Capture that AssistantMessage and attempt to save it to JdbcChatMemoryRepository.
- Since textContent == null, the following SQL fails:
INSERT INTO SPRING_AI_CHAT_MEMORY (conversation_id, content, type, timestamp)
VALUES (?, NULL, 'ASSISTANT', ?)
.
Expected behavior
The repository should store the response with null value
Minimal Complete Reproducible example
Here is the code that caused the bug in my project.
fun call(conversationId: String, prompt: Prompt, toolCallingChatOption: ToolCallingChatOptions?): ChatResponse {
val systemMessage = prompt.systemMessage
chatMemory.add(conversationId, prompt.userMessage)
val promptWithMemory = Prompt(chatMemory.get(conversationId) + prompt.systemMessage, toolCallingChatOption)
var chatResponse = chatModel.call(promptWithMemory) ?: throw ErrorCode.CHAT_NULL_RESPONSE.toException()
chatMemory.add(conversationId, chatResponse.result.output) // throw Exception
}