fix: sanitize empty text content blocks in /v1/messages endpoint#22933
Merged
krrishdholakia merged 1 commit intoBerriAI:litellm_oss_staging_03_06_2026from Mar 7, 2026
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Greptile SummaryThis PR adds Key implementation details:
Confidence Score: 5/5
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Client sends /v1/messages request\n(multi-turn tool-use conversation)"] --> B["anthropic_messages()"]
B --> C["_sanitize_anthropic_messages(messages)"]
C --> D{"For each message:\ncontent is a list?"}
D -- No --> E["Pass through unchanged"]
D -- Yes --> F["Filter: remove blocks where\ntype=text AND text is empty/whitespace"]
F --> G{"Any blocks\nremoved?"}
G -- No --> E
G -- Yes --> H{"filtered list\nnon-empty?"}
H -- Yes --> I["Replace message with shallow copy\n{**message, content: filtered}"]
H -- No --> J["Replace message with\ncontinuation message\n(DEFAULT_ASSISTANT_CONTINUE_MESSAGE)"]
I --> K["Return sanitized messages list"]
J --> K
E --> K
K --> L["_execute_pre_request_hooks()"]
L --> M["Route to provider\n(Anthropic direct / Bedrock / etc.)"]
Last reviewed commit: e8e2a27 |
litellm/llms/anthropic/experimental_pass_through/messages/handler.py
Outdated
Show resolved
Hide resolved
litellm/llms/anthropic/experimental_pass_through/messages/handler.py
Outdated
Show resolved
Hide resolved
86e2b90 to
60adc81
Compare
litellm/llms/anthropic/experimental_pass_through/messages/handler.py
Outdated
Show resolved
Hide resolved
60adc81 to
7fe6a21
Compare
7fe6a21 to
ad47c19
Compare
...erimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py
Outdated
Show resolved
Hide resolved
The `/v1/messages` endpoint does not sanitize empty text content blocks
from messages, causing 400 errors ("text content blocks must be
non-empty") in multi-turn tool-use conversations.
Claude's API returns assistant messages with empty text blocks alongside
`tool_use` blocks (e.g., `{"type": "text", "text": ""}`). While the API
returns these, it rejects them when sent back in subsequent requests.
The `/v1/chat/completions` path already handles this via
`process_empty_text_blocks()` in `factory.py`, but the `/v1/messages`
path was missing equivalent sanitization.
Fix: Add `_sanitize_anthropic_messages()` at the entry point of the
`/v1/messages` handler, before any routing. This strips empty/whitespace
text blocks from message content arrays while preserving non-empty text
and other block types (`tool_use`, `tool_result`, etc.). The function
does not leave content arrays empty to avoid a different validation error.
This affects all providers routed through `/v1/messages` (Anthropic
direct, Bedrock Converse, Azure, etc.) and is particularly important for
Claude Code / Agent SDK conversations which frequently produce these
patterns.
Fixes BerriAI#22930
ad47c19 to
e8e2a27
Compare
dsteeley
added a commit
to dsteeley/litellm
that referenced
this pull request
Mar 6, 2026
…s fallback
Strict OpenAI-compatible models (e.g. Kimi-K2.5, gpt-oss-120b on Azure AI)
reject messages whose content array contains {"type": "text", "text": ""}.
These empty parts are produced by the Responses API -> chat/completions
transformation when an assistant turn contains a tool call alongside an
empty text block.
Add _strip_empty_text_content_parts() to handler.py and call it in both
the sync (response_api_handler) and async (async_response_api_handler)
paths before litellm.completion() / litellm.acompletion(). The helper is
a no-op when no empty parts are present (returns the original dict).
Related to PR BerriAI#22933 which fixes the same class of bug in the /v1/messages
path.
7 tasks
a4fe061
into
BerriAI:litellm_oss_staging_03_06_2026
28 of 38 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/v1/messagesendpoint before forwarding to providersProblem
The Anthropic API returns assistant messages with empty text blocks alongside
tool_useblocks:{"type": "text", "text": ""}, {"type": "tool_use", "id": "toolu_xxx", "name": "Bash", "input": {...}}While the API returns these, it rejects them when sent back in subsequent requests. The
/anthropicpassthrough handles this transparently, but the/v1/messagesnative path (used for Anthropic direct and Bedrock) passes messages through without sanitization.The
/v1/chat/completionspath already handles this viaprocess_empty_text_blocks()infactory.py, but the/v1/messagespath was missing equivalent sanitization.modify_params=Truedoes not help as it targets a different code path.Fix
Add
_sanitize_anthropic_messages()at the entry point ofanthropic_messages()in the/v1/messageshandler, before any routing. This strips empty/whitespace-only text blocks from message content arrays while preserving non-empty text and other block types (tool_use,tool_result, etc.). Does not leave content arrays empty to avoid a different validation error.Testing
/v1/messagesto both Anthropic direct and Bedrock ConverseFixes #22930