Problem
Streaming and non-streaming HTTP errors produce inconsistent error messages:
- Non-streaming 401:
Anthropic API error: Invalid API Key (via _handle_error_response())
- Streaming 401:
Client error '401 Unauthorized' for url 'https://api.anthropic.com/v1/messages' (via raw raise_for_status())
Both raise httpx.HTTPStatusError, but streaming errors lack the provider-enriched message that parses the JSON error body.
Root cause
stream_post() lives on HTTPClient (src/celeste/http.py:189) — a transport-only class with no provider context. _handle_error_response() lives on ModalityClient (src/celeste/client.py:353-371), which has access to self.provider and JSON body parsing. There is no back-reference from HTTPClient to ModalityClient by design.
PR #192 correctly added raise_for_status() to stream_post() — this is strictly better than the old behavior where streaming HTTP errors were silently swallowed. The enrichment gap is a pre-existing architectural limitation.
Suggested fix
Have _make_stream_request() in the protocol clients wrap the stream_post() async iterator to catch httpx.HTTPStatusError and re-raise with enriched messages using the existing _handle_error_response() logic.
Both ChatCompletionsClient._make_stream_request() (src/celeste/protocols/chatcompletions/client.py:93-111) and OpenResponsesClient._make_stream_request() (src/celeste/protocols/openresponses/client.py:93-111) currently return self.http_client.stream_post(...) directly. They could instead wrap it in an async generator that catches and enriches HTTP errors at the protocol layer where provider context is available.
Key files
src/celeste/http.py:189 — raise_for_status() call
src/celeste/client.py:353-371 — _handle_error_response() implementation
src/celeste/protocols/chatcompletions/client.py:93-111 — streaming request path
src/celeste/protocols/openresponses/client.py:93-111 — streaming request path
Found during code review of #192.
Problem
Streaming and non-streaming HTTP errors produce inconsistent error messages:
Anthropic API error: Invalid API Key(via_handle_error_response())Client error '401 Unauthorized' for url 'https://api.anthropic.com/v1/messages'(via rawraise_for_status())Both raise
httpx.HTTPStatusError, but streaming errors lack the provider-enriched message that parses the JSON error body.Root cause
stream_post()lives onHTTPClient(src/celeste/http.py:189) — a transport-only class with no provider context._handle_error_response()lives onModalityClient(src/celeste/client.py:353-371), which has access toself.providerand JSON body parsing. There is no back-reference fromHTTPClienttoModalityClientby design.PR #192 correctly added
raise_for_status()tostream_post()— this is strictly better than the old behavior where streaming HTTP errors were silently swallowed. The enrichment gap is a pre-existing architectural limitation.Suggested fix
Have
_make_stream_request()in the protocol clients wrap thestream_post()async iterator to catchhttpx.HTTPStatusErrorand re-raise with enriched messages using the existing_handle_error_response()logic.Both
ChatCompletionsClient._make_stream_request()(src/celeste/protocols/chatcompletions/client.py:93-111) andOpenResponsesClient._make_stream_request()(src/celeste/protocols/openresponses/client.py:93-111) currently returnself.http_client.stream_post(...)directly. They could instead wrap it in an async generator that catches and enriches HTTP errors at the protocol layer where provider context is available.Key files
src/celeste/http.py:189—raise_for_status()callsrc/celeste/client.py:353-371—_handle_error_response()implementationsrc/celeste/protocols/chatcompletions/client.py:93-111— streaming request pathsrc/celeste/protocols/openresponses/client.py:93-111— streaming request pathFound during code review of #192.