spring-projects / spring-projects/spring-ai

ToolResponseMessage results in null content, causing SQLIntegrityConstraintViolationException in JdbcChatMemoryRepository

Open
#3,339 2 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
9.5k
Forks
2.9k
Avg merge
1d 10h
Merged PRs (30d)
5

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

  1. Use a ChatModel that returns a response containing only toolCalls (e.g., OpenAI with function/tool calling).
  2. Capture that AssistantMessage and attempt to save it to JdbcChatMemoryRepository.
  3. 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
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at JdbcChatMemoryRepository and trace the insert path used for an AssistantMessage containing only toolCalls, then compare it with the provided INSERT statement and the database constraint on content. Reproduce the case with a tool-call-only ChatResponse and verify that the repository handles the message without a SQLIntegrityConstraintViolationException.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, mariadb, sql
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.