Skip to content

fix: handle Claude streaming error events to prevent session corruption on overload#1513

Open
octo-patch wants to merge 1 commit into
sigoden:mainfrom
octo-patch:fix/issue-1463-claude-streaming-error-events
Open

fix: handle Claude streaming error events to prevent session corruption on overload#1513
octo-patch wants to merge 1 commit into
sigoden:mainfrom
octo-patch:fix/issue-1463-claude-streaming-error-events

Conversation

@octo-patch

Copy link
Copy Markdown

Fixes #1463

Problem

When Claude returns an overload error (HTTP 529 or SSE error event), the session can become corrupted with an empty assistant message, causing all subsequent requests to fail:

Error: Failed to call chat-completions api

Caused by:
    messages.1: all messages must have non-empty content except for the optional final assistant message

Root cause — two issues:

  1. SSE error events silently ignored: When Claude returns HTTP 200 but sends an SSE event with "type": "error" (e.g. overloaded_error), the streaming handler falls through to the _ => {} catch-all and ignores it. This results in empty output being treated as a successful completion. The empty string is then saved as an assistant message in the session, corrupting it for future requests.

  2. catch_error misses {"code": N, "detail": "..."} shape: Anthropic's 529 response uses "code" as the key (not "status"), so the existing {"status": N, "detail": "..."} branch in catch_error never matched. The error fell through to the generic fallback with an uninformative message.

Solution

  1. src/client/claude.rs: Add explicit handling for "error" type SSE events in claude_chat_completions_streaming. When a Claude error event arrives, bail with the error type and message instead of silently ignoring it.

  2. src/client/common.rs: Extend catch_error to also match the {"code": N, "detail": "..."} response shape, producing a clear "Overloaded (status: 529)" error message.

Testing

  • Built and verified the code compiles cleanly.
  • The fix ensures that Claude overload errors surface as proper errors rather than silently corrupting the session with an empty assistant message.

…messages (fixes sigoden#1463)

Two related fixes for the Claude overload (HTTP 529) error:

1. claude.rs: Add explicit handling for SSE events with type "error" in the
   streaming handler. Previously, Claude error events sent within a 200 streaming
   response (e.g. overloaded_error) were silently ignored via the `_ => {}` catch-all,
   resulting in empty output being saved to the session. The session would then
   contain an empty assistant message, causing subsequent requests to fail with
   "all messages must have non-empty content".

2. common.rs: Extend catch_error to handle the {"code": N, "detail": "..."} response
   shape (used by Anthropic's 529 overloaded responses) in addition to the existing
   {"status": N, "detail": "..."} shape.

Co-Authored-By: Octopus <liyuan851277048@icloud.com>
ei-grad added a commit to ei-grad/aichat that referenced this pull request Jul 11, 2026
Accumulate OpenAI tool calls across every delta entry and split reused
indexes only when a new non-empty call ID arrives. Validate complete JSON
arguments before dispatch and serialize the stream flag in both modes.

Surface Claude SSE provider errors and numeric code/detail HTTP errors so
failed requests cannot be treated as empty successful completions. Add
deterministic regression fixtures for continuation chunks, call boundaries,
parallel deltas, invalid JSON, and successful control streams.

Reimplements fixes from:
sigoden#1496
sigoden#1511
sigoden#1513

Co-Authored-By: Codex CLI <noreply@openai.com>
ei-grad added a commit to ei-grad/aichat that referenced this pull request Jul 11, 2026
Treat transport EOF as truncation unless the provider handler confirms
protocol completion. This prevents OpenAI tool calls from being flushed
without [DONE] and keeps Claude tool_use blocks staged until a matching
content_block_stop and the final message_stop.

Track Claude block indexes so mismatched deltas and stops fail closed. Keep
normal text, reasoning, provider errors, and Cohere's [DONE] completion path
unchanged.

Remediates the streaming review finding in integrations based on:
sigoden#1496
sigoden#1511
sigoden#1513

Co-Authored-By: Codex CLI <noreply@openai.com>
ei-grad added a commit to ei-grad/aichat that referenced this pull request Jul 11, 2026
Integrate the exact upstream PR head and retain its provider-error handling
and numeric error details. The named streaming follow-up adds deterministic
state and completion controls without rewriting this source commit.

Source: sigoden#1513
Head: 2c68b4f
ei-grad added a commit to ei-grad/aichat that referenced this pull request Jul 11, 2026
Extend the imported OpenAI and Claude foundations with index-aware multi-call
accumulation, complete JSON validation, deterministic request serialization,
and provider-error controls. Preserve the exact PR commits in ancestry while
replacing their incomplete accumulator and boundary behavior with the reviewed
combined contract and focused tests.

Sources:
sigoden#1496
sigoden#1511
sigoden#1513
Reviewed behavior: 2dd73a2

Co-Authored-By: Codex CLI <noreply@openai.com>
ei-grad added a commit to ei-grad/aichat that referenced this pull request Jul 11, 2026
Integrate the named provider-state branch after the exact sigoden#1496, sigoden#1511, and
sigoden#1513 imports. The second parent records the reviewed multi-call, validation,
and deterministic streaming test contract.

Sources:
sigoden#1496
sigoden#1511
sigoden#1513
ei-grad added a commit to ei-grad/aichat that referenced this pull request Jul 11, 2026
Treat transport EOF as truncation unless the provider handler confirms
protocol completion. This prevents OpenAI tool calls from being flushed
without [DONE] and keeps Claude tool_use blocks staged until a matching
content_block_stop and the final message_stop.

Track Claude block indexes so mismatched deltas and stops fail closed. Keep
normal text, reasoning, provider errors, and Cohere's [DONE] completion path
unchanged.

Remediates the streaming review finding in integrations based on:
sigoden#1496
sigoden#1511
sigoden#1513

Co-Authored-By: Codex CLI <noreply@openai.com>
ei-grad added a commit to ei-grad/aichat that referenced this pull request Jul 11, 2026
Integrate the named fail-closed completion branch after provider streaming and
credential remediation. The second parent records OpenAI [DONE] and Claude
block/message-stop requirements without dispatching pending side effects on
transport EOF.

Sources:
sigoden#1496
sigoden#1511
sigoden#1513
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Claude overload error handling

1 participant