fix: handle Claude streaming error events to prevent session corruption on overload#1513
Open
octo-patch wants to merge 1 commit into
Open
Conversation
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
Root cause — two issues:
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.catch_errormisses{"code": N, "detail": "..."}shape: Anthropic's 529 response uses"code"as the key (not"status"), so the existing{"status": N, "detail": "..."}branch incatch_errornever matched. The error fell through to the generic fallback with an uninformative message.Solution
src/client/claude.rs: Add explicit handling for"error"type SSE events inclaude_chat_completions_streaming. When a Claude error event arrives, bail with the error type and message instead of silently ignoring it.src/client/common.rs: Extendcatch_errorto also match the{"code": N, "detail": "..."}response shape, producing a clear"Overloaded (status: 529)"error message.Testing