diff --git a/src/anthropic/lib/bedrock/_stream_decoder.py b/src/anthropic/lib/bedrock/_stream_decoder.py index 02e81a3ca..7a0a0e768 100644 --- a/src/anthropic/lib/bedrock/_stream_decoder.py +++ b/src/anthropic/lib/bedrock/_stream_decoder.py @@ -1,9 +1,13 @@ from __future__ import annotations +import json from typing import TYPE_CHECKING, Iterator, AsyncIterator +import httpx + from ..._utils import lru_cache from ..._streaming import ServerSentEvent +from ..._exceptions import APIStatusError, InternalServerError, BadRequestError, RateLimitError if TYPE_CHECKING: from botocore.model import Shape @@ -55,10 +59,35 @@ def _parse_message_from_event(self, event: EventStreamMessage) -> str | None: response_dict = event.to_response_dict() parsed_response = self.parser.parse(response_dict, get_response_stream_shape()) if response_dict["status_code"] != 200: - raise ValueError(f"Bad response code, expected 200: {response_dict}") + self._raise_for_bedrock_stream_error(response_dict) chunk = parsed_response.get("chunk") if not chunk: return None return chunk.get("bytes").decode() # type: ignore[no-any-return] + + def _raise_for_bedrock_stream_error(self, response_dict: dict[str, object]) -> None: + status_code = int(response_dict["status_code"]) # type: ignore[arg-type] + body_bytes = response_dict.get("body", b"") + try: + body = json.loads(body_bytes) # type: ignore[arg-type] + except Exception: + body = {} + + message = body.get("message") or f"Bedrock event stream error (status {status_code})" + + # Build a minimal synthetic response so APIStatusError is satisfied. + synthetic_response = httpx.Response( + status_code=status_code, + request=httpx.Request("POST", "https://bedrock-runtime.amazonaws.com"), + ) + + if status_code == 429: + raise RateLimitError(message, response=synthetic_response, body=body) + if status_code >= 500: + raise InternalServerError(message, response=synthetic_response, body=body) + if status_code == 400: + raise BadRequestError(message, response=synthetic_response, body=body) + + raise APIStatusError(message, response=synthetic_response, body=body)