From 6da33f469a93887dccb10587c58c07bc5ac1c63a Mon Sep 17 00:00:00 2001 From: 4444jPPP Date: Fri, 27 Mar 2026 14:32:43 -0400 Subject: [PATCH] fix(bedrock,vertex): add missing 413 and 529 status error handling The Bedrock and Vertex clients' _make_status_error methods were missing handlers for HTTP 413 (RequestTooLargeError) and 529 (OverloadedError). These were already handled in the main Anthropic/AsyncAnthropic clients (added in #1244), but the Bedrock and Vertex variants fell through to the generic InternalServerError (for 529) or APIStatusError (for 413). This makes error handling consistent across all client variants, so users can catch specific exception types regardless of which provider they use. --- src/anthropic/lib/bedrock/_client.py | 6 +++++ src/anthropic/lib/vertex/_client.py | 6 +++++ tests/lib/test_bedrock.py | 35 ++++++++++++++++++++++++ tests/lib/test_vertex.py | 40 ++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/src/anthropic/lib/bedrock/_client.py b/src/anthropic/lib/bedrock/_client.py index 013d2702..e6405831 100644 --- a/src/anthropic/lib/bedrock/_client.py +++ b/src/anthropic/lib/bedrock/_client.py @@ -114,6 +114,9 @@ def _make_status_error( if response.status_code == 409: return _exceptions.ConflictError(err_msg, response=response, body=body) + if response.status_code == 413: + return _exceptions.RequestTooLargeError(err_msg, response=response, body=body) + if response.status_code == 422: return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body) @@ -123,6 +126,9 @@ def _make_status_error( if response.status_code == 503: return _exceptions.ServiceUnavailableError(err_msg, response=response, body=body) + if response.status_code == 529: + return _exceptions.OverloadedError(err_msg, response=response, body=body) + if response.status_code >= 500: return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) diff --git a/src/anthropic/lib/vertex/_client.py b/src/anthropic/lib/vertex/_client.py index af916aa7..4f82f125 100644 --- a/src/anthropic/lib/vertex/_client.py +++ b/src/anthropic/lib/vertex/_client.py @@ -70,6 +70,9 @@ def _make_status_error( if response.status_code == 409: return _exceptions.ConflictError(err_msg, response=response, body=body) + if response.status_code == 413: + return _exceptions.RequestTooLargeError(err_msg, response=response, body=body) + if response.status_code == 422: return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body) @@ -82,6 +85,9 @@ def _make_status_error( if response.status_code == 504: return _exceptions.DeadlineExceededError(err_msg, response=response, body=body) + if response.status_code == 529: + return _exceptions.OverloadedError(err_msg, response=response, body=body) + if response.status_code >= 500: return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) diff --git a/tests/lib/test_bedrock.py b/tests/lib/test_bedrock.py index fe62da43..9ce9b889 100644 --- a/tests/lib/test_bedrock.py +++ b/tests/lib/test_bedrock.py @@ -9,6 +9,19 @@ from respx import MockRouter from anthropic import AnthropicBedrock, AsyncAnthropicBedrock +from anthropic._exceptions import ( + BadRequestError, + AuthenticationError, + PermissionDeniedError, + NotFoundError, + ConflictError, + RequestTooLargeError, + UnprocessableEntityError, + RateLimitError, + ServiceUnavailableError, + OverloadedError, + InternalServerError, +) sync_client = AnthropicBedrock( aws_region="us-east-1", @@ -195,3 +208,25 @@ def test_region_infer_from_specified_profile( client = AnthropicBedrock() assert client.aws_region == next(profile for profile in profiles if profile["name"] == aws_profile)["region"] + + +@pytest.mark.parametrize( + "status_code, expected_error", + [ + (400, BadRequestError), + (401, AuthenticationError), + (403, PermissionDeniedError), + (404, NotFoundError), + (409, ConflictError), + (413, RequestTooLargeError), + (422, UnprocessableEntityError), + (429, RateLimitError), + (500, InternalServerError), + (503, ServiceUnavailableError), + (529, OverloadedError), + ], +) +def test_make_status_error(status_code: int, expected_error: type) -> None: + response = httpx.Response(status_code, request=httpx.Request("GET", "/")) + err = sync_client._make_status_error("msg", body=None, response=response) + assert type(err) is expected_error diff --git a/tests/lib/test_vertex.py b/tests/lib/test_vertex.py index 2c7906c5..a02b3d5f 100644 --- a/tests/lib/test_vertex.py +++ b/tests/lib/test_vertex.py @@ -9,6 +9,20 @@ from respx import MockRouter from anthropic import AnthropicVertex, AsyncAnthropicVertex +from anthropic._exceptions import ( + BadRequestError, + AuthenticationError, + PermissionDeniedError, + NotFoundError, + ConflictError, + RequestTooLargeError, + UnprocessableEntityError, + RateLimitError, + ServiceUnavailableError, + DeadlineExceededError, + OverloadedError, + InternalServerError, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -276,3 +290,29 @@ def test_env_var_base_url_override(self, monkeypatch: pytest.MonkeyPatch) -> Non base_url="https://test.googleapis.com/v1", ) assert str(client.base_url).rstrip("/") == "https://test.googleapis.com/v1" + + +vertex_client = AnthropicVertex(region="region", project_id="project", access_token="my-access-token") + + +@pytest.mark.parametrize( + "status_code, expected_error", + [ + (400, BadRequestError), + (401, AuthenticationError), + (403, PermissionDeniedError), + (404, NotFoundError), + (409, ConflictError), + (413, RequestTooLargeError), + (422, UnprocessableEntityError), + (429, RateLimitError), + (500, InternalServerError), + (503, ServiceUnavailableError), + (504, DeadlineExceededError), + (529, OverloadedError), + ], +) +def test_make_status_error(status_code: int, expected_error: type) -> None: + response = httpx.Response(status_code, request=httpx.Request("GET", "/")) + err = vertex_client._make_status_error("msg", body=None, response=response) + assert type(err) is expected_error