Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion src/anthropic/lib/bedrock/_stream_decoder.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)