-
Notifications
You must be signed in to change notification settings - Fork 2k
Fix OpenAI streaming finish_reason handling for empty string values #4132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
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
This commit addresses issues with OpenAI streaming responses where
finish_reason is an empty string ("") instead of null, which caused
Jackson deserialization failures and inconsistent metadata formatting.
Changes:
- Configure Jackson coercion in ModelOptionsUtils to handle empty
string to enum conversion (empty string -> null)
- Fix getFinishReasonJson() method in OpenAiChatModel to return
uppercase enum names for backward compatibility
- Fix null pointer exceptions in streaming processing by ensuring
getFinishReasonJson() returns empty string instead of null
- Maintain finish_reason metadata as uppercase enum names
("STOP", "LENGTH") to preserve backward compatibility
- Add comprehensive test suite covering all edge cases
- Update streaming tests to expect correct uppercase finish reason values
Key fixes:
1. Empty string finish_reason now deserializes correctly without errors
2. Finish reason metadata maintains backward compatibility (uppercase enum names)
3. No more NullPointerException in streaming Map.of() calls
4. Proper handling of null, empty string, and valid finish_reason values
Jackson coercion configuration in ModelOptionsUtils now converts empty
strings to null for ALL enum deserialization across Spring AI. Analysis
shows this change is safe and beneficial for other providers:
- Anthropic, Ollama use String fields (unaffected by enum coercion)
- ZhiPuAI, MiniMax, MistralAI, DeepSeek use enum fields but have no
documented empty string issues
- Coercion improves robustness by gracefully handling malformed responses
- No breaking changes expected for existing provider implementations
Testing:
- Added OpenAiStreamingFinishReasonTests with 6 comprehensive test cases
- Fixed existing metadata tests to maintain backward compatibility
- All tests pass, covering JSON deserialization and streaming scenarios
- Validates both error handling and correct behavior
- Added tests for changes to ModelOptionsUtils using enum coersion
This ensures robust handling of OpenAI's empty string finish_reason edge
case while maintaining backward compatibility and improving overall
system resilience for malformed API responses.
Auto-cherry-pick to 1.0.x
Fixes #1358
Signed-off-by: Mark Pollack <[email protected]>
spring-builds
pushed a commit
that referenced
this pull request
Aug 13, 2025
…4132) This commit addresses issues with OpenAI streaming responses where finish_reason is an empty string ("") instead of null, which caused Jackson deserialization failures and inconsistent metadata formatting. Changes: - Configure Jackson coercion in ModelOptionsUtils to handle empty string to enum conversion (empty string -> null) - Fix getFinishReasonJson() method in OpenAiChatModel to return uppercase enum names for backward compatibility - Fix null pointer exceptions in streaming processing by ensuring getFinishReasonJson() returns empty string instead of null - Maintain finish_reason metadata as uppercase enum names ("STOP", "LENGTH") to preserve backward compatibility - Add comprehensive test suite covering all edge cases - Update streaming tests to expect correct uppercase finish reason values Key fixes: 1. Empty string finish_reason now deserializes correctly without errors 2. Finish reason metadata maintains backward compatibility (uppercase enum names) 3. No more NullPointerException in streaming Map.of() calls 4. Proper handling of null, empty string, and valid finish_reason values Jackson coercion configuration in ModelOptionsUtils now converts empty strings to null for ALL enum deserialization across Spring AI. Analysis shows this change is safe and beneficial for other providers: - Anthropic, Ollama use String fields (unaffected by enum coercion) - ZhiPuAI, MiniMax, MistralAI, DeepSeek use enum fields but have no documented empty string issues - Coercion improves robustness by gracefully handling malformed responses - No breaking changes expected for existing provider implementations Testing: - Added OpenAiStreamingFinishReasonTests with 6 comprehensive test cases - Fixed existing metadata tests to maintain backward compatibility - All tests pass, covering JSON deserialization and streaming scenarios - Validates both error handling and correct behavior - Added tests for changes to ModelOptionsUtils using enum coersion This ensures robust handling of OpenAI's empty string finish_reason edge case while maintaining backward compatibility and improving overall system resilience for malformed API responses. Fixes #1358 Signed-off-by: Mark Pollack <[email protected]> (cherry picked from commit 653918d)
scionaltera
pushed a commit
to scionaltera/spring-ai
that referenced
this pull request
Sep 3, 2025
…pring-projects#4132) This commit addresses issues with OpenAI streaming responses where finish_reason is an empty string ("") instead of null, which caused Jackson deserialization failures and inconsistent metadata formatting. Changes: - Configure Jackson coercion in ModelOptionsUtils to handle empty string to enum conversion (empty string -> null) - Fix getFinishReasonJson() method in OpenAiChatModel to return uppercase enum names for backward compatibility - Fix null pointer exceptions in streaming processing by ensuring getFinishReasonJson() returns empty string instead of null - Maintain finish_reason metadata as uppercase enum names ("STOP", "LENGTH") to preserve backward compatibility - Add comprehensive test suite covering all edge cases - Update streaming tests to expect correct uppercase finish reason values Key fixes: 1. Empty string finish_reason now deserializes correctly without errors 2. Finish reason metadata maintains backward compatibility (uppercase enum names) 3. No more NullPointerException in streaming Map.of() calls 4. Proper handling of null, empty string, and valid finish_reason values Jackson coercion configuration in ModelOptionsUtils now converts empty strings to null for ALL enum deserialization across Spring AI. Analysis shows this change is safe and beneficial for other providers: - Anthropic, Ollama use String fields (unaffected by enum coercion) - ZhiPuAI, MiniMax, MistralAI, DeepSeek use enum fields but have no documented empty string issues - Coercion improves robustness by gracefully handling malformed responses - No breaking changes expected for existing provider implementations Testing: - Added OpenAiStreamingFinishReasonTests with 6 comprehensive test cases - Fixed existing metadata tests to maintain backward compatibility - All tests pass, covering JSON deserialization and streaming scenarios - Validates both error handling and correct behavior - Added tests for changes to ModelOptionsUtils using enum coersion This ensures robust handling of OpenAI's empty string finish_reason edge case while maintaining backward compatibility and improving overall system resilience for malformed API responses. Auto-cherry-pick to 1.0.x Fixes spring-projects#1358 Signed-off-by: Mark Pollack <[email protected]>
chedim
pushed a commit
to couchbaselabs/spring-ai
that referenced
this pull request
Sep 19, 2025
…pring-projects#4132) This commit addresses issues with OpenAI streaming responses where finish_reason is an empty string ("") instead of null, which caused Jackson deserialization failures and inconsistent metadata formatting. Changes: - Configure Jackson coercion in ModelOptionsUtils to handle empty string to enum conversion (empty string -> null) - Fix getFinishReasonJson() method in OpenAiChatModel to return uppercase enum names for backward compatibility - Fix null pointer exceptions in streaming processing by ensuring getFinishReasonJson() returns empty string instead of null - Maintain finish_reason metadata as uppercase enum names ("STOP", "LENGTH") to preserve backward compatibility - Add comprehensive test suite covering all edge cases - Update streaming tests to expect correct uppercase finish reason values Key fixes: 1. Empty string finish_reason now deserializes correctly without errors 2. Finish reason metadata maintains backward compatibility (uppercase enum names) 3. No more NullPointerException in streaming Map.of() calls 4. Proper handling of null, empty string, and valid finish_reason values Jackson coercion configuration in ModelOptionsUtils now converts empty strings to null for ALL enum deserialization across Spring AI. Analysis shows this change is safe and beneficial for other providers: - Anthropic, Ollama use String fields (unaffected by enum coercion) - ZhiPuAI, MiniMax, MistralAI, DeepSeek use enum fields but have no documented empty string issues - Coercion improves robustness by gracefully handling malformed responses - No breaking changes expected for existing provider implementations Testing: - Added OpenAiStreamingFinishReasonTests with 6 comprehensive test cases - Fixed existing metadata tests to maintain backward compatibility - All tests pass, covering JSON deserialization and streaming scenarios - Validates both error handling and correct behavior - Added tests for changes to ModelOptionsUtils using enum coersion This ensures robust handling of OpenAI's empty string finish_reason edge case while maintaining backward compatibility and improving overall system resilience for malformed API responses. Auto-cherry-pick to 1.0.x Fixes spring-projects#1358 Signed-off-by: Mark Pollack <[email protected]>
Willam2004
pushed a commit
to Willam2004/spring-ai
that referenced
this pull request
Oct 11, 2025
…pring-projects#4132) This commit addresses issues with OpenAI streaming responses where finish_reason is an empty string ("") instead of null, which caused Jackson deserialization failures and inconsistent metadata formatting. Changes: - Configure Jackson coercion in ModelOptionsUtils to handle empty string to enum conversion (empty string -> null) - Fix getFinishReasonJson() method in OpenAiChatModel to return uppercase enum names for backward compatibility - Fix null pointer exceptions in streaming processing by ensuring getFinishReasonJson() returns empty string instead of null - Maintain finish_reason metadata as uppercase enum names ("STOP", "LENGTH") to preserve backward compatibility - Add comprehensive test suite covering all edge cases - Update streaming tests to expect correct uppercase finish reason values Key fixes: 1. Empty string finish_reason now deserializes correctly without errors 2. Finish reason metadata maintains backward compatibility (uppercase enum names) 3. No more NullPointerException in streaming Map.of() calls 4. Proper handling of null, empty string, and valid finish_reason values Jackson coercion configuration in ModelOptionsUtils now converts empty strings to null for ALL enum deserialization across Spring AI. Analysis shows this change is safe and beneficial for other providers: - Anthropic, Ollama use String fields (unaffected by enum coercion) - ZhiPuAI, MiniMax, MistralAI, DeepSeek use enum fields but have no documented empty string issues - Coercion improves robustness by gracefully handling malformed responses - No breaking changes expected for existing provider implementations Testing: - Added OpenAiStreamingFinishReasonTests with 6 comprehensive test cases - Fixed existing metadata tests to maintain backward compatibility - All tests pass, covering JSON deserialization and streaming scenarios - Validates both error handling and correct behavior - Added tests for changes to ModelOptionsUtils using enum coersion This ensures robust handling of OpenAI's empty string finish_reason edge case while maintaining backward compatibility and improving overall system resilience for malformed API responses. Auto-cherry-pick to 1.0.x Fixes spring-projects#1358 Signed-off-by: Mark Pollack <[email protected]> Signed-off-by: 家娃 <[email protected]>
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.
This commit addresses issues with OpenAI streaming responses where finish_reason is an empty string ("") instead of null, which caused Jackson deserialization failures and inconsistent metadata formatting.
Changes:
Key fixes:
Jackson coercion configuration in ModelOptionsUtils now converts empty strings to null for ALL enum deserialization across Spring AI. Analysis shows this change is safe and beneficial for other providers:
Testing:
This ensures robust handling of OpenAI's empty string finish_reason edge case while maintaining backward compatibility and improving overall system resilience for malformed API responses.
Auto-cherry-pick to 1.0.x
Fixes #1358
Thank you for taking time to contribute this pull request!
You might have already read the contributor guide, but as a reminder, please make sure to:
git commit -s) per the DCOmainbranch and squash your commitsFor more details, please check the contributor guide.
Thank you upfront!