spring-projects / spring-projects/spring-ai
OpenAiChatModel serializes empty content on assistant tool_call messages, causing 400
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.5k
- Forks
- 2.9k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 5
Description
Bug description
During the multi-turn tool-call loop, OpenAiChatModel.createRequest() serializes
"content":"" (empty string) on assistant messages that carry tool_calls. When
using an OpenAI-compatible backend that proxies to Anthropic/Claude (e.g. Heroku
Inference), the API rejects this with HTTP 400:messages[6]: content is required
OpenAI's own API tolerates "content":"", but Anthropic's API requires content to
be either a non-empty string or null. Since spring-ai-starter-model-openai is
designed to work with any OpenAI-compatible endpoint, the serialization should
produce valid payloads for all compliant backends.
Environment
- Spring AI: 1.1.2
- Spring Boot: 3.5.9
- Java: 17
- Backend: Heroku Inference (OpenAI-compatible, proxies to Claude-Opus 4-5)
Steps to reproduce
- Configure
spring-ai-starter-model-openaiwith an Anthropic-compatible endpoint - Register a
@Toolfunction - Send a user message that triggers the model to call the tool
- The model responds with
tool_callsand no text content - Spring AI executes the tool locally, then sends the conversation history
(including the assistant tool_call message) back to the API - HTTP 400:
"messages[N]: content is required"
Expected behavior
The assistant message should have "content": null (not "") when the model
response only contained tool calls and no text. Example:
Minimal Complete Reproducible example
{"role":"assistant","content":null,"tool_calls":[{"id":"...","type":"function","function":{"name":"myTool","arguments":"{}"}}]}
Full stack
org.springframework.ai.retry.NonTransientAiException: HTTP 400 -
{"error":{"code":400,"message":"messages[6]: content is required","type":"invalid_request"}}
at o.s.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration$2.handleError(SpringAiRetryAutoConfiguration.java:126)
at o.s.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:58)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at OpenAiChatModel.createRequest and reproduce the multi-turn tool-call flow against an OpenAI-compatible endpoint. Inspect the assistant message produced after a tool call and verify that empty content is serialized as null rather than an empty string. Done means the resulting request matches the provided example and is accepted by the compatible backend.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring, spring-boot
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100