fix(models): treat a part-less candidate as an error, not a success - #1417
Open
svetanis wants to merge 1 commit into
Open
fix(models): treat a part-less candidate as an error, not a success#1417svetanis wants to merge 1 commit into
svetanis wants to merge 1 commit into
Conversation
hemasekhar-p
force-pushed
the
fix/partless-candidate
branch
from
August 10, 2026 10:51
efd53fa to
e0e9425
Compare
Contributor
|
Hi @svetanis, thank you for your contribution! We appreciate you taking the time to submit this pull request. Currently this PR is under review by our team, we will keep you posted if any additional information is required. thank you. |
svetanis
force-pushed
the
fix/partless-candidate
branch
from
August 10, 2026 23:49
168d5ad to
e0e9425
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
2. Or, if no issue exists, describe the change:
Problem:
LlmResponse.Builder.response(GenerateContentResponse)decides success by testing whether thecandidate's content object is present, never whether it holds anything. A candidate cut off
mid-generation arrives with
contentpresent and part-less ("content": {}on the wire), socandidate.content().isPresent()sends it down the success branch:errorCodeanderrorMessagestay empty, and
finishMessageis discarded. The caller receives an empty answer that reads exactlylike a model with nothing to say.
errorCodeis documented as "Error code if the response is an error", yet the result carriesfinishReason=MAX_TOKENSwitherrorCodeempty.Solution:
One predicate. Decide on whether the candidate produced parts, and treat a
STOPwith nothing tosay as a legitimate empty turn:
Two rows of behavior change, both in this branch:
STOPreasonerrorCode+errorMessagefrom the candidatefinishReason=STOPerrorCode=STOP— a normal turn marked as an errorEverything else is untouched: parts present is still a success whatever the reason, a part-less
STOPstill succeeds, a blocked prompt still becomeserrorCodefromblockReason, and theno-candidates path is unchanged.
core/src/main/java/…/models/LlmResponse.javacore/src/test/java/…/models/LlmResponseTest.javaTesting Plan
Unit Tests:
Eight in
LlmResponseTest. The four marked as failing were confirmed failing on unmodifiedmainbefore the change, by reverting
LlmResponse.javaalone and re-running:maintestCreate_partlessCandidateOutOfTokens_isReportedAsErrorMAX_TOKENSerrorCodefrom the finish reason, no contenttestCreate_partlessCandidateBlocked_reportsFinishMessageAsErrorSAFETYerrorCode+errorMessagefromfinishMessagetestCreate_candidateWithEmptyPartsList_isReportedAsErrorpartslist,MAX_TOKENStestCreate_contentlessCandidateStoppedNormally_isReportedAsSuccessSTOPtestCreate_candidateWithEmptyTextPart_isReportedAsSuccessMAX_TOKENStestCreate_partlessCandidateStoppedNormally_isReportedAsSuccessSTOPtestCreate_partlessCandidateWithoutFinishReason_reportsNeitherContentNorErrortestCreate_truncatedCandidateWithText_isReportedAsSuccessMAX_TOKENSThe four that already pass are the guards. They describe behavior this change must leave alone, so
they only break if the classification is inverted rather than tightened.
Manual End-to-End (E2E) Tests:
LlmAgentongemini-3.1-flash-litewithmaxOutputTokens=24andthinkingBudget=2048returns a part-lessMAX_TOKENScandidate on demand. Before the change it isreported as a success and the caller receives an empty answer; after it, the same response carries
errorCode=MAX_TOKENS. A control arm on an ordinary budget answers normally in both runs, and atruncated-but-non-empty answer stays a success in both.
Checklist