aws-samples / aws-samples/sample-bedrock-proxy-gateway
Streaming error handler raises httpx.ResponseNotRead, masking the real error
- Dominant language
- Python
- Stars
- 12
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Context
On the streaming endpoints, the error handler reads `e.response.text` after `raise_for_status()` on a response opened with `client.stream(...)`. A streamed body isn't read automatically, so accessing `.text` raises `httpx.ResponseNotRead`. The handler itself throws, and the real upstream error is lost.
Specifically, the error reads:
_**httpx.ResponseNotRead: Attempted to access streaming response content, without having called `read()`.**_
Moving `await e.response.aread()` into the `except` block doesn't help either: by then the `async with client.stream(...)` context has closed the stream, raising `httpx.StreamClosed`.
## Affected code
1) `bedrock_routes.py`- the `except httpx.HTTPStatusError` branches in the `converse-stream` and `invoke-with-response-stream` generators read `e.response.text`, but the body was never read (`raise_for_status()` fires before any `aiter_bytes()`).
2) `bedrock_service_httpx.py` - same pattern in the STS handler (`e.response.text[:200]` on a non-OK streamed response).
## Suggested fix
1) In `bedrock_routes.py`, check the status and read the body **inside** the `async with` block (before it closes): replace `raise_for_status()` + the `HTTPStatusError` branch with an explicit `if resp.status_code >= 400: await resp.aread()` then surface `resp.text`.
2) In `bedrock_service_httpx.py`, add `await e.response.aread()` before reading `e.response.text`.
Note: Reproducible with a local server returning 403 on a streaming POST. In this scenario, `e.response.text` raises `httpx.ResponseNotRead`; reading inside the `async with` returns the body.
Contributor guide
Research direction
Start in bedrock_routes.py at the converse-stream and invoke-with-response-stream error branches, then inspect the matching STS handler in bedrock_service_httpx.py. Reproduce the failure with a local server returning 403 for a streaming POST and trace response lifetime inside async with. Done means the upstream error body is surfaced without ResponseNotRead or StreamClosed masking it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100