Skip to content

fix: streaming HTTP errors lack provider-enriched error messages #194

Description

@Kamilbenkirane

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:189raise_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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions