Fix streaming error handling and frontend reconnection#382
Merged
Conversation
d2f7bf5 to
3f8672e
Compare
Backend: - Setup failures in execute_chat (session creation, model config) now emit a proper error event via emit_bootstrap_error: persists the error to DB, publishes to Redis pub/sub, and updates the message snapshot with consistent last_seq and FAILED status. Preserves any partial response already flushed and appends a renderable assistant_text error event to content_render so the error is visible on reload. - Scheduler's direct execute_chat call gets the same error handling. - Extract duplicated QUEUE_PROCESSING sniffing in chat.py into _extract_queue_processing_message_id helper. - Remove orphaned outer try block from execute_chat after moving failure handling to _bootstrap_and_execute. Frontend: - Remove lastConnectedStreamRef guard that blocked callback refresh when callbacks changed but the stream ID stayed the same. Add activeStreams identity guard so the subscription only fires when the stream set actually changes. - Add direct store check in useStreamReconnect to prevent double EventSource connections. Use getStreamByChat instead of Array.from(...).some(...). - onError now marks the assistant message as failed instead of removing it from cache/UI, and flushes buffered accumulator content before clearing the stream session. - Seed off-screen stream accumulators from the query cache so the first off-screen chunk doesn't overwrite cached content. - Replace ES2020-incompatible findLast with a reverse for loop.
3f8672e to
210af81
Compare
Document the requirement to trace callback lifecycles before flagging closure bugs — prevents false positives where a helper appears to use the current chatId but is actually frozen from an earlier render.
This was referenced May 8, 2026
pull Bot
pushed a commit
to woakes070048/claudex
that referenced
this pull request
May 9, 2026
Fill in the harness content layer that PR 1 routed to. Each artifact
doc captures the rules an agent must know before writing that artifact
type; each domain map gives entry points, vocabulary, gotchas, and
verified prior-art PRs.
Backend artifacts (docs/artifacts/backend/):
- models.md — SQLAlchemy 2.x async, Mapped[], custom column types,
Alembic workflow, anti-patterns
- endpoints.md — FastAPI route handlers, deps.py wiring, domain
exceptions, auth dependencies, SSE/WS conventions
- services.md — class-based service shape, BaseDbService, exception
discipline, integration boundaries
- tests.md — endpoint-tests-only, conftest fixtures, fake providers,
stub-vs-real boundaries
- integrations.md — Docker, GitHub, ACP, SMTP, Redis ownership matrix
Frontend artifacts (docs/artifacts/frontend/):
- components.md — React 19 patterns, primitives, contexts/providers,
hooks discipline, anti-patterns
- state.md — Zustand vs context vs useState decision tree
- data-fetching.md — TanStack Query setup, query-key factory, prefix
keys for cwd-scoped invalidation, mutation patterns
- styling.md — Tailwind tokens, monochrome palette, primitives,
typography/icon/animation rules
Domain maps (docs/domains/):
- chat.md — entities, message state machine, queue/send-now,
cross-domain edges; PRs Mng-dev-ai#592, Mng-dev-ai#593, Mng-dev-ai#594, Mng-dev-ai#560, Mng-dev-ai#419, Mng-dev-ai#251, Mng-dev-ai#454
- sandbox.md — Docker vs Host providers, lifecycle; PRs Mng-dev-ai#590, Mng-dev-ai#588,
Mng-dev-ai#531, Mng-dev-ai#505, Mng-dev-ai#551, Mng-dev-ai#594
- providers.md — ACP adapter registry, per-agent quirks, persona
gating; PRs Mng-dev-ai#591, Mng-dev-ai#589, Mng-dev-ai#528, Mng-dev-ai#499, Mng-dev-ai#542, Mng-dev-ai#538, Mng-dev-ai#541, Mng-dev-ai#465, Mng-dev-ai#537
- streaming.md — StreamEnvelope, seq-based reconnection, snapshot vs
control events; PRs Mng-dev-ai#370, #173, #190, Mng-dev-ai#382, Mng-dev-ai#432, Mng-dev-ai#346, Mng-dev-ai#214, Mng-dev-ai#524, Mng-dev-ai#471, #192
- auth.md — fastapi-users, refresh tokens, encrypted-at-rest,
WS auth handshake; PRs Mng-dev-ai#586, Mng-dev-ai#587, Mng-dev-ai#589, Mng-dev-ai#449, Mng-dev-ai#550, Mng-dev-ai#469
- git.md — GitService surface, worktrees, ChatCheckpoint;
PRs Mng-dev-ai#592, Mng-dev-ai#594, Mng-dev-ai#593, Mng-dev-ai#596, Mng-dev-ai#527, Mng-dev-ai#398, Mng-dev-ai#402
- workspace.md — workspaces, skills, personas, slash commands;
PRs Mng-dev-ai#598, Mng-dev-ai#597, Mng-dev-ai#596, Mng-dev-ai#506, Mng-dev-ai#510, Mng-dev-ai#537, Mng-dev-ai#542, Mng-dev-ai#561, Mng-dev-ai#414, Mng-dev-ai#464, Mng-dev-ai#476, Mng-dev-ai#563
Each prior-art PR was verified via gh pr view (state=MERGED, files
within the cited domain) before citation.
Cleanup:
- AGENTS.md: removed PR-1's "Doc status" footer; routing tables now
point at real files. The github.md route was rolled into git.md and
workspace.md (no separate domain map needed at current surface area).
- docs/legacy.md deleted — content now lives in the per-artifact docs
it sourced.
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.
Summary
execute_chat()(session creation, model config, transport errors) now emit a proper error event instead of silently crashing and leaving the SSE client hanging forever. New_emit_bootstrap_error()persists the error event to DB, publishes to Redis pub/sub, and updates the message snapshot with consistentlast_seq/FAILEDstatus. Preserves any partial response already flushed.execute_chat()call now has the same bootstrap error handling, preventing scheduled-task chats from getting stuck in streaming state.lastConnectedStreamRefguard that blocked callback refresh when callbacks changed but the stream ID stayed the same.useStreamReconnectto prevent double EventSource connections, making the 100ms setTimeout a performance optimization rather than a correctness requirement.findLastwith a reverse for loop.Test plan
set_modelto throw) and verify the SSE client receives an error event, the message is marked FAILED, and the frontend shows an error state