Skip to content

SSE stream error events are silently discarded — add error detection to streaming pipeline #144

Description

@Kamilbenkirane

Bug

When a provider sends an error event mid-stream (e.g., Anthropic's {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}), the error is silently discarded. The consumer receives partial content with no indication that an error occurred.

Reproduction

The silent discard path:

  1. stream_post() in http.py yields the error event (valid JSON ✅)
  2. Provider's _parse_chunk_content()None (not a recognized content event type)
  3. Provider's _parse_chunk_usage()None
  4. Provider's _parse_chunk_finish_reason()None
  5. _parse_chunk()None (all three returned None)
  6. Stream.__anext__() silently skips it (if chunk is not None: ...)
  7. Error vanishes — never logged, never raised, never stored in metadata

This affects all SSE-based text providers: Anthropic, OpenAI, Google, Cohere, DeepSeek, Groq, Mistral, Moonshot, xAI, OpenResponses.

Additional Notes

  • SSE_EVENT_ERROR = "error" is defined in src/celeste/providers/anthropic/messages/config.py (line 51) but never imported or referenced anywhere — dead code.
  • http.py's stream_post() does not call raise_for_status() before iterating SSE events (unlike stream_post_ndjson which does).
  • The only provider with any error detection is BytePlus Images (stuffs error into chunk metadata, doesn't raise) and Gradium TTS (raises, but WebSocket-based, not SSE).

Proposed Fix

Add error detection to the base streaming pipeline. Two options:

Option A — Provider streaming mixin (recommended):
Each provider's streaming mixin adds a _handle_stream_error(event_data) method that checks for provider-specific error event types and raises. Called at the start of _parse_chunk().

Option B — Base Stream.__anext__:
Add a generic check before _parse_chunk() that looks for common error patterns (event.get("error"), event.get("type") == "error").

Option A is preferred because error event formats differ across providers (Anthropic uses {"type": "error"}, OpenAI uses different patterns, etc.).

Affected Files

  • src/celeste/streaming.py — optionally add base error hook
  • src/celeste/providers/*/streaming.py — add _handle_stream_error() to each provider's streaming mixin
  • src/celeste/http.py — consider adding raise_for_status() to stream_post() for HTTP-level errors

🤖 Generated with Claude Code

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