From 36ea4689ef972cb7bda5abb59bc5721c49196581 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 21:05:46 +0000 Subject: [PATCH] fix(bedrock): substitute continue message for blank string user content in converse --- .../prompt_templates/factory.py | 4 +- ...llm_core_utils_prompt_templates_factory.py | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py index f7ff4d6b16f..783eee2a8e3 100644 --- a/litellm/litellm_core_utils/prompt_templates/factory.py +++ b/litellm/litellm_core_utils/prompt_templates/factory.py @@ -4395,7 +4395,7 @@ class BedrockConverseMessagesProcessor: _parts.append(_cache_point_block) user_content.extend(_parts) elif message_block["content"] and isinstance(message_block["content"], str): - _part = BedrockContentBlock(text=messages[msg_i]["content"]) + _part = BedrockContentBlock(text=message_block["content"]) _cache_point_block = litellm.AmazonConverseConfig()._get_cache_point_block( message_block, block_type="content_block", model=model ) @@ -4770,7 +4770,7 @@ def _bedrock_converse_messages_pt( _parts.append(_cache_point_block) user_content.extend(_parts) elif message_block["content"] and isinstance(message_block["content"], str): - _part = BedrockContentBlock(text=messages[msg_i]["content"]) + _part = BedrockContentBlock(text=message_block["content"]) _cache_point_block = litellm.AmazonConverseConfig()._get_cache_point_block( message_block, block_type="content_block", model=model ) diff --git a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py index bcda88ea609..b08b63fca58 100644 --- a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py +++ b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py @@ -182,6 +182,55 @@ def test_bedrock_converse_assistant_with_empty_thinking_block_and_tool_calls(): assert len(tool_use_blocks) == 2 +@pytest.mark.parametrize("content", ["", " ", "\n\t "]) +def test_bedrock_converse_blank_string_user_message_substituted_sync(content): + """ + Regression for https://github.com/BerriAI/litellm/issues/33016 + + A user message whose content is a blank/whitespace-only string must be + replaced with the "Please continue." continue message (issue #7169), + because Bedrock Converse rejects blank-text ContentBlocks. The + string-content branch previously forwarded the original, un-substituted + text. + """ + litellm.modify_params = True + try: + result = _bedrock_converse_messages_pt( + messages=[{"role": "user", "content": content}], + model="anthropic.claude-3-sonnet-20240229-v1:0", + llm_provider="bedrock", + ) + finally: + litellm.modify_params = False + + user_blocks = [m for m in result if m["role"] == "user"] + assert len(user_blocks) == 1 + texts = [b["text"] for b in user_blocks[0]["content"] if "text" in b] + assert texts == ["Please continue."] + + +@pytest.mark.asyncio +@pytest.mark.parametrize("content", ["", " ", "\n\t "]) +async def test_bedrock_converse_blank_string_user_message_substituted_async(content): + """ + Async counterpart of the #33016 regression test. + """ + litellm.modify_params = True + try: + result = await BedrockConverseMessagesProcessor._bedrock_converse_messages_pt_async( + messages=[{"role": "user", "content": content}], + model="anthropic.claude-3-sonnet-20240229-v1:0", + llm_provider="bedrock", + ) + finally: + litellm.modify_params = False + + user_blocks = [m for m in result if m["role"] == "user"] + assert len(user_blocks) == 1 + texts = [b["text"] for b in user_blocks[0]["content"] if "text" in b] + assert texts == ["Please continue."] + + @pytest.mark.parametrize( "thinking_block", [