Fix: Skip empty text blocks in Anthropic system messages (#17442)

When translating system messages for the Anthropic API, empty text
content blocks cause the error "messages: text content blocks must be
non-empty". This fix skips empty string content and empty text blocks
in list content to prevent this error.

Fixes issue with Vertex AI Anthropic API calls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Haiyi 2025-12-04 16:25:06 +11:00 • committed by GitHub
parent a6ce118989
commit 06d42fbd30
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 94 additions and 2 deletions

View file

@ -786,6 +786,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
valid_content: bool = False
system_message_block = ChatCompletionSystemMessage(**message)
if isinstance(system_message_block["content"], str):
# Skip empty text blocks - Anthropic API raises errors for empty text
if not system_message_block["content"]:
continue
anthropic_system_message_content = AnthropicSystemMessageContent(
type="text",
text=system_message_block["content"],
@ -800,10 +803,14 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
valid_content = True
elif isinstance(message["content"], list):
for _content in message["content"]:
# Skip empty text blocks - Anthropic API raises errors for empty text
text_value = _content.get("text")
if _content.get("type") == "text" and not text_value:
continue
anthropic_system_message_content = (
AnthropicSystemMessageContent(
type=_content.get("type"),
text=_content.get("text"),
text=text_value,
)
)
if "cache_control" in _content:

View file

@ -1290,10 +1290,95 @@ def test_effort_with_other_features():
litellm_params={},
headers={}
)
# Verify all features are present
assert "output_config" in result
assert result["output_config"]["effort"] == "low"
assert "tools" in result
assert len(result["tools"]) > 0
assert "thinking" in result
def test_translate_system_message_skips_empty_string_content():
"""
Test that translate_system_message skips system messages with empty string content.
Fixes: Vertex AI Anthropic API error "messages: text content blocks must be non-empty"
"""
config = AnthropicConfig()
# Test empty string content - should not produce any anthropic system message content
messages = [
{"role": "system", "content": ""},
{"role": "user", "content": "Hello"},
]
result = config.translate_system_message(messages)
# Empty system message should produce no anthropic content blocks
assert len(result) == 0
def test_translate_system_message_skips_empty_list_content():
"""
Test that translate_system_message skips empty text blocks in list content.
Fixes: Vertex AI Anthropic API error "messages: text content blocks must be non-empty"
"""
config = AnthropicConfig()
# Test list content with empty text block
messages = [
{"role": "system", "content": [
{"type": "text", "text": ""},
{"type": "text", "text": "Valid content"},
{"type": "text", "text": ""},
]},
{"role": "user", "content": "Hello"},
]
result = config.translate_system_message(messages)
# Only non-empty text blocks should be included
assert len(result) == 1
assert result[0]["text"] == "Valid content"
def test_translate_system_message_preserves_valid_content():
"""
Test that translate_system_message preserves valid system message content.
"""
config = AnthropicConfig()
# Test valid string content
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello"},
]
result = config.translate_system_message(messages)
assert len(result) == 1
assert result[0]["type"] == "text"
assert result[0]["text"] == "You are a helpful assistant."
def test_translate_system_message_preserves_cache_control():
"""
Test that translate_system_message preserves cache_control on valid content.
"""
config = AnthropicConfig()
# Test list content with cache_control
messages = [
{"role": "system", "content": [
{"type": "text", "text": "Cached content", "cache_control": {"type": "ephemeral"}},
]},
{"role": "user", "content": "Hello"},
]
result = config.translate_system_message(messages)
assert len(result) == 1
assert result[0]["text"] == "Cached content"
assert result[0]["cache_control"] == {"type": "ephemeral"}