From 7260c3a7277dae3e80aaf2083d9da2dded7688ca Mon Sep 17 00:00:00 2001 From: Rishab Motgi Date: Mon, 18 May 2026 16:48:37 -0700 Subject: [PATCH] test: add regression test for empty-choices guard in raise_on_model_repetition Verifies that metadata-only chunks (choices=[]) from Vertex Gemini Flash with web_search_options do not crash raise_on_model_repetition with IndexError, and that _repeated_messages_count is correctly reset to 1 on those chunks. --- .../test_streaming_handler.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/test_litellm/litellm_core_utils/test_streaming_handler.py b/tests/test_litellm/litellm_core_utils/test_streaming_handler.py index 49d3c51e340..fe723f11114 100644 --- a/tests/test_litellm/litellm_core_utils/test_streaming_handler.py +++ b/tests/test_litellm/litellm_core_utils/test_streaming_handler.py @@ -1511,6 +1511,37 @@ def test_raise_on_model_repetition( wrapper.raise_on_model_repetition() +def test_raise_on_model_repetition_empty_choices_no_crash( + initialized_custom_stream_wrapper: CustomStreamWrapper, +): + """ + Regression test: Vertex Gemini Flash with web_search_options emits + metadata-only chunks with choices=[]. raise_on_model_repetition must + not raise IndexError on those chunks, and must reset the repetition + counter to 1 so subsequent real chunks are compared correctly. + """ + wrapper = initialized_custom_stream_wrapper + + empty_chunk = ModelResponseStream( + id="test", + created=1741037890, + model="test-model", + choices=[], # metadata-only chunk — no choices + ) + + # Two empty-choices chunks: should not crash and counter should stay at 1 + wrapper.chunks.append(empty_chunk) + wrapper.chunks.append(empty_chunk) + wrapper.raise_on_model_repetition() # must not raise IndexError + assert wrapper._repeated_messages_count == 1 + + # Real content chunk after metadata chunks should still be compared correctly + real_chunk = _make_chunk("hello world content") + wrapper.chunks.append(real_chunk) + wrapper.raise_on_model_repetition() # still must not raise + assert wrapper._repeated_messages_count == 1 + + def test_usage_chunk_after_finish_reason_updates_hidden_params(logging_obj): """ Test that provider-reported usage from a post-finish_reason chunk