From ac679561f534125538f2cd1ed86cbb2970828e56 Mon Sep 17 00:00:00 2001 From: Mateo Wang <277851410+mateo-berri@users.noreply.github.com> Date: Wed, 24 Jun 2026 08:06:27 -0700 Subject: [PATCH] fix(anthropic): skip content-less keepalive chunks in streaming bridge A chunk with empty choices and no usage carries no content, billing, or finish reason, so translating it emitted a premature message_delta and broke Anthropic SSE ordering. Skip such keepalives in both the sync and async iterator loops; usage-only trailing chunks (choices=[] with usage) still flow through. --- .../adapters/streaming_iterator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py index 3aec95f5c02..ddb6e7b7021 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py @@ -388,6 +388,9 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): if chunk == "None" or chunk is None: raise Exception + if not chunk.choices and getattr(chunk, "usage", None) is None: + continue + should_start_new_block = self._should_start_new_content_block(chunk) if should_start_new_block: self._increment_content_block_index() @@ -609,6 +612,9 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): if chunk == "None" or chunk is None: raise Exception + if not chunk.choices and getattr(chunk, "usage", None) is None: + continue + # Check if we need to start a new content block should_start_new_block = self._should_start_new_content_block(chunk) if should_start_new_block: