From d958282f297ea458785d58b85869ff628eec72af Mon Sep 17 00:00:00 2001 From: weiguangli-io Date: Mon, 27 Apr 2026 19:42:48 +0800 Subject: [PATCH] fix(bedrock): filter empty text blocks from assistant messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #26554. When Claude's streamed responses are replayed via the Anthropic /v1/messages → Bedrock Invoke path, empty text content blocks ({"type":"text","text":""}) from the leading content_block_start event are preserved. Bedrock rejects these with "text field is blank". Filter out empty text blocks from assistant messages before sending to Bedrock, matching the existing guard in the Converse path. --- .../anthropic_claude3_transformation.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py index 96593b35d0c..ad2803d4726 100644 --- a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py @@ -513,6 +513,26 @@ class AmazonAnthropicClaudeMessagesConfig( normalize_tool_input_schema_types_for_bedrock_invoke(anthropic_messages_request) ensure_bedrock_anthropic_messages_tool_names(anthropic_messages_request) + # 5b. Filter empty text blocks from assistant messages. + # Bedrock rejects {"type":"text","text":""} with: + # "The text field in the ContentBlock object is blank." + # These empty blocks come from Claude's streamed responses that emit + # a leading content_block_start with empty text. + # Ref: https://github.com/BerriAI/litellm/issues/26554 + for msg in anthropic_messages_request.get("messages", []): + if msg.get("role") == "assistant" and isinstance( + msg.get("content"), list + ): + msg["content"] = [ + block + for block in msg["content"] + if not ( + isinstance(block, dict) + and block.get("type") == "text" + and not block.get("text", "").strip() + ) + ] + # 6. AUTO-INJECT beta headers based on features used anthropic_model_info = AnthropicModelInfo() tools = anthropic_messages_optional_request_params.get("tools")