fix(anthropic): validate messages only when a beta-gated drop runs

A non-object messages entry on a Claude model without mid-conversation
system support raised a raw pydantic ValidationError before the
beta-config and drop_params checks. The strip now passes the messages
through untouched unless it drops something, so the provider's 400
reaches SDK callers as BadRequestError again
This commit is contained in:
mateo-berri 2026-10-28 20:08:41 -07:00
parent aedc352aaa
commit c768f9062c
2 changed files with 19 additions and 6 deletions

View file

@ -231,14 +231,13 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
return system_param
def _strip_beta_gated_system_turns(
self, messages: Sequence[object], model: str, drop_params: object
) -> tuple[Mapping[str, object], ...]:
validated: Final = _MESSAGE_MAPPINGS.validate_python(messages)
self, messages: Sequence[Mapping[str, object]], model: str, drop_params: object
) -> Sequence[Mapping[str, object]]:
if not has_beta_headers_config(self._resolved_provider):
return validated
gated: Final = strip_beta_gated_system_messages(validated, frozenset(), drop_params=drop_params)
return messages
gated: Final = strip_beta_gated_system_messages(messages, frozenset(), drop_params=drop_params)
log_beta_gated_strips(gated.stripped, model=model, provider=self._resolved_provider)
return _MESSAGE_MAPPINGS.validate_python(gated.messages) if gated.stripped else validated
return _MESSAGE_MAPPINGS.validate_python(gated.messages) if gated.stripped else messages
def _normalize_system_role_messages(
self, anthropic_messages_request: dict, model: str, drop_params: object

View file

@ -851,6 +851,20 @@ class TestVertexAnthropicMidConversationSystem:
{"type": "text", "text": "Cite sources."},
]
@pytest.mark.parametrize("drop_params", (False, True))
def test_unsupported_model_sends_a_non_object_message_on_for_the_provider_to_reject(
self, local_model_cost_map, local_beta_headers_config, drop_params
):
messages: Final = [{"role": "user", "content": "hi"}, "oops"]
result: Final = VertexAIPartnerModelsAnthropicMessagesConfig().transform_anthropic_messages_request(
model="claude-sonnet-4-6",
messages=list(messages),
anthropic_messages_optional_request_params={"max_tokens": 64},
litellm_params=GenericLiteLLMParams(drop_params=drop_params),
headers={},
)
assert result["messages"] == messages
def test_unsupported_model_converts_mid_conversation_system_in_place(self, local_model_cost_map):
messages = [
{"role": "user", "content": "read the file"},