From 9ad4a5af30191be323a95350b56778411c91a514 Mon Sep 17 00:00:00 2001 From: Saylee Date: Fri, 9 Oct 2026 00:26:12 +0530 Subject: [PATCH] fix(streaming): keep delta.refusal chunks instead of dropping them --- .../litellm_core_utils/streaming_handler.py | 1 + .../test_streaming_handler.py | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/litellm/litellm_core_utils/streaming_handler.py b/litellm/litellm_core_utils/streaming_handler.py index 9bb5b761fd5..78e8309cc30 100644 --- a/litellm/litellm_core_utils/streaming_handler.py +++ b/litellm/litellm_core_utils/streaming_handler.py @@ -1056,6 +1056,7 @@ class CustomStreamWrapper: and model_response.choices[0].delta.role is not None ) or (getattr(model_response.choices[0].delta, "reasoning_items", None) is not None) + or (getattr(model_response.choices[0].delta, "refusal", None) is not None) ): return True else: diff --git a/tests/unit/litellm_core_utils/test_streaming_handler.py b/tests/unit/litellm_core_utils/test_streaming_handler.py index da88f1358ad..05d87566737 100644 --- a/tests/unit/litellm_core_utils/test_streaming_handler.py +++ b/tests/unit/litellm_core_utils/test_streaming_handler.py @@ -270,6 +270,31 @@ def test_is_chunk_non_empty(initialized_custom_stream_wrapper: CustomStreamWrapp ) +def test_is_chunk_non_empty_with_refusal( + initialized_custom_stream_wrapper: CustomStreamWrapper, +): + """Unit test if non-empty when the delta carries only a refusal""" + chunk: Final = { + "id": "chatcmpl-abc", + "object": "chat.completion.chunk", + "created": 1700000000, + "model": "m", + "choices": [ + { + "index": 0, + "delta": {"refusal": "I can't help"}, + "logprobs": None, + "finish_reason": None, + } + ], + } + assert initialized_custom_stream_wrapper.is_chunk_non_empty( + completion_obj=MagicMock(), + model_response=ModelResponseStream(**chunk), + response_obj=MagicMock(), + ) + + def test_is_chunk_non_empty_with_annotations( initialized_custom_stream_wrapper: CustomStreamWrapper, ):