fix(anthropic): route usage-limit 400 through rate-limit detection

The helper change alone was not on the Anthropic exception path:
_map_anthropic_exception maps the invalid_request_error (400) usage-limit
response to BadRequestError before any rate-limit check runs. Call
is_error_str_rate_limit inside the Anthropic mapper, ahead of the 400
branches, so it surfaces as RateLimitError (429) as documented. Add an
end-to-end test driving exception_type for the reported payload.
This commit is contained in:
72004 2026-08-21 22:11:38 +05:00
parent 74dc2e782b
commit 9c1eb0ec33
2 changed files with 36 additions and 0 deletions

View file

@ -598,6 +598,17 @@ def _map_anthropic_exception(
model=model,
llm_provider="anthropic",
)
# Anthropic returns usage/spend-limit exhaustion typed as invalid_request_error (400),
# but per the exception-mapping docs it should surface as a RateLimitError (429). Check
# before the generic 400 branches below, which would otherwise map it to BadRequestError.
if ExceptionCheckers.is_error_str_rate_limit(
error_str, getattr(original_exception, "status_code", None)
):
raise RateLimitError(
message=f"AnthropicError - {error_str}",
model=model,
llm_provider="anthropic",
)
if "Client error '400 Bad Request'" in error_str:
raise BadRequestError(
message=f"AnthropicError - {error_str}",

View file

@ -218,6 +218,31 @@ class TestExceptionCheckers:
)
assert ExceptionCheckers.is_error_str_rate_limit(error_str, status_code=400) is True
def test_anthropic_usage_limit_maps_to_rate_limit_error_end_to_end(self):
"""Production path: an Anthropic usage-limit error is typed invalid_request_error
(HTTP 400). Driving it through exception_type must surface a RateLimitError (429),
not a BadRequestError (#37599) — the helper alone is not on the Anthropic mapper.
"""
message = (
"AnthropicException - "
'{"type":"error","error":{"type":"invalid_request_error",'
'"message":"You have reached your specified API usage limits. '
'You will regain access on 2026-09-01 at 00:00 UTC."},'
'"request_id":"req_011CeDfeyYs7N6neZrLwFxPJ"}'
)
original_exception = httpx.HTTPStatusError(
message=message,
request=httpx.Request("POST", "https://api.anthropic.com/v1/messages"),
response=httpx.Response(400),
)
with pytest.raises(litellm.RateLimitError):
exception_type(
model="claude-haiku-4-5-20251001",
original_exception=original_exception,
custom_llm_provider="anthropic",
)
def test_is_azure_content_policy_violation_error_with_policy_violation_text(self):
"""Test detection of Azure content policy violation with explicit policy violation text"""