Skip to content

fix: filter empty-text parts in GoogleGenAiChatModel to prevent API errors (#4556)#5762

Open
anuragg-saxenaa wants to merge 1 commit intospring-projects:mainfrom
anuragg-saxenaa:fix/issue-4556-empty-assistant-messages-google-genai
Open

fix: filter empty-text parts in GoogleGenAiChatModel to prevent API errors (#4556)#5762
anuragg-saxenaa wants to merge 1 commit intospring-projects:mainfrom
anuragg-saxenaa:fix/issue-4556-empty-assistant-messages-google-genai

Conversation

@anuragg-saxenaa
Copy link
Copy Markdown

Problem

Fixes #4556

When using Spring AI's Google GenAI integration with tool calling and chat memory (MessageChatMemoryAdvisor), the Google API sometimes returns candidates whose parts contain no text content (e.g. thought-signature-only parts or server-side tool invocation parts with no accompanying text).

The previous code produced AssistantMessage instances with content("") for these parts. When MessageChatMemoryAdvisor stored these in chat history and they were sent back on subsequent requests, the Google API rejected the request with a missing parts field error, breaking multi-turn conversations as soon as a tool-calling turn produced any empty-text candidate parts.

Root Cause

In responseCandidateToGeneration, the stream mapped every non-toolCall/non-toolResponse part to a Generation using part.text().orElse("") — including parts with no text at all. These empty AssistantMessage objects then round-tripped through messageToParts, which correctly skips empty text (line 309 guard), resulting in a Content with an empty parts list that the API rejects.

Fix

Two targeted changes to GoogleGenAiChatModel:

  1. responseCandidateToGeneration — add a filter so only parts with actual text produce generations
  2. toGeminiContent — filter out Content items with empty parts before sending to the API as a defensive backstop

Tests

Two new unit tests in GoogleGenAiChatModelExtendedUsageTests (no live API key required):

  • testResponseCandidateWithEmptyTextPartsProducesNoEmptyGenerations
  • testToGeminiContentFiltersOutEmptyPartContent

…rrors

Fixes spring-projects#4556

When the Google GenAI API returns a candidate whose parts contain no text
(e.g. thought-signature-only or server-side tool-invocation parts), the
response converter was producing AssistantMessages with empty content.
When these empty messages were stored in chat memory and sent in subsequent
requests, the Google API rejected them with 'missing parts field' errors,
breaking multi-turn conversations with tool calling.

Two fixes applied:

1. responseCandidateToGeneration: add filter on part.text() presence
   so only parts with actual text content produce generations.
   Uses part.text().get() after the filter guard (no orElse needed).

2. toGeminiContent: filter out Content items whose parts list is empty
   before building the API request, so a stale empty-content
   AssistantMessage in chat memory cannot cause a 400 error.

Also adds two unit tests in GoogleGenAiChatModelExtendedUsageTests
covering both the empty-part candidate response and the clean text-part
round-trip, so regressions are caught without a live API key.

Signed-off-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
@anuragg-saxenaa anuragg-saxenaa force-pushed the fix/issue-4556-empty-assistant-messages-google-genai branch from 1626ee5 to a4c5c84 Compare April 6, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Google GenAI integration adds empty assistant messages to chat history, causing API errors on subsequent requests

1 participant