fix(bedrock/claude_platform): warn when claude_platform_unsupported_params has an invalid type

A present but non-collection claude_platform_unsupported_params was silently
ignored, so an operator who mistyped the value (e.g. a string) got the default
filtering with no feedback. resolve_unsupported_override now logs a WARNING that
names the param in that case, mirroring the existing dropped-param warning. The
header-derivation pass passes log_invalid=False so the message is emitted once
per request rather than twice on the native /v1/messages path.
This commit is contained in:
mateo-berri 2026-06-25 14:32:50 +00:00
parent 934ae7dd7f
commit 06b44105e8
No known key found for this signature in database
3 changed files with 34 additions and 15 deletions

View file

@ -78,18 +78,30 @@ def filter_claude_platform_request_body(
def resolve_unsupported_override(
litellm_params: Union[dict[str, object], GenericLiteLLMParams],
log_invalid: bool = True,
) -> Optional[frozenset[str]]:
"""Read ``claude_platform_unsupported_params`` from litellm_params.
Returns None (use default set) when the key is absent. Returns a
frozenset when present, allowing operators to override or clear the
unsupported-param list via proxy config without a code change.
Returns None (use the default set) when the key is absent or set to a
non-collection type; returns a frozenset when a list/set/tuple is given,
letting operators override or clear the unsupported-param list via proxy
config without a code change. A present but non-collection value is a
misconfiguration: it is ignored (defaults apply) and logged at WARNING when
``log_invalid`` is set, so operators see the override had no effect. The
header-derivation pass disables it so the warning fires once per request.
"""
raw = litellm_params.get("claude_platform_unsupported_params")
if raw is None:
return None
if isinstance(raw, (list, set, frozenset, tuple)):
return frozenset(str(item) for item in raw)
if log_invalid:
verbose_logger.warning(
"bedrock/claude_platform: ignoring claude_platform_unsupported_params "
"of unsupported type %s; expected a list/set/tuple of param names. "
"Using the default unsupported-param set.",
type(raw).__name__,
)
return None

View file

@ -52,7 +52,9 @@ class BedrockClaudePlatformMessagesConfig(
if resolved_api_key and "x-api-key" not in headers:
headers["x-api-key"] = resolved_api_key
unsupported_override = resolve_unsupported_override(litellm_params)
unsupported_override = resolve_unsupported_override(
litellm_params, log_invalid=False
)
filtered_optional_params = filter_claude_platform_request_body(
optional_params,
unsupported_override=unsupported_override,

View file

@ -485,26 +485,31 @@ def test_claude_platform_unsupported_override_allows_context_management():
def test_claude_platform_unsupported_override_ignores_invalid_type():
"""
If claude_platform_unsupported_params is set to a non-collection type
(e.g. a string), the override is ignored and defaults apply.
(e.g. a string), the override is ignored, defaults apply, and a warning
naming the param is logged so the operator sees it had no effect.
"""
from litellm.llms.bedrock.claude_platform import common_utils
from litellm.llms.bedrock.claude_platform.transformation import (
BedrockClaudePlatformConfig,
)
config = BedrockClaudePlatformConfig()
request_body = config.transform_request(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "hello"}],
optional_params={
"context_management": {"edits": [{"type": "clear_tool_uses_20250919"}]},
"max_tokens": 10,
},
litellm_params={"claude_platform_unsupported_params": "not_a_list"},
headers={},
)
with patch.object(common_utils.verbose_logger, "warning") as mock_warning:
request_body = config.transform_request(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "hello"}],
optional_params={
"context_management": {"edits": [{"type": "clear_tool_uses_20250919"}]},
"max_tokens": 10,
},
litellm_params={"claude_platform_unsupported_params": "not_a_list"},
headers={},
)
assert "context_management" not in request_body
assert request_body["max_tokens"] == 10
warned = [call.args[0] for call in mock_warning.call_args_list]
assert any("claude_platform_unsupported_params" in message for message in warned)
def test_claude_platform_messages_does_not_advertise_beta_for_stripped_context_management():