fix(server): set session to error state when sendTurn fails#1960
fix(server): set session to error state when sendTurn fails#1960sachssem wants to merge 1 commit intopingdotgg:mainfrom
Conversation
When sendTurn fails server-side after the client dispatch succeeds, the catchCause handler only appended a failure activity without updating the thread session. This left the client unable to detect the failure: isSendBusy stayed true and the "Working for …" indicator hung indefinitely because hasServerAcknowledgedLocalDispatch never observed a phase, error, or snapshot change. After appending the failure activity, transition the thread session to reflect the failure. When an active provider binding exists, set status to "error" so the binding is preserved for recovery. When no binding exists (e.g. provider mismatch before session start, or a previously stopped session), set status to "stopped" to avoid creating a synthetic session that looks bound without a backing ProviderService directory entry. Both paths set lastError so the client observes threadError, resets localDispatch, and re-enables the composer. Adds regression tests for the existing-session, null-session, and stopped-session failure paths, plus a recovery test confirming that a subsequent turn succeeds after a provider-switch error.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved This is a focused bug fix that properly transitions session state to 'error' when sendTurn fails, fixing a hanging UI indicator. The code change is self-contained within an existing error handler, and 85% of the diff is comprehensive test coverage for the new behavior. You can customize Macroscope's approvability policy. Learn more. |
What Changed
When
sendTurnForThreadfails insideProviderCommandReactor, thecatchCausehandler now also callssetThreadSessionto transition the session into a terminal state, in addition to the existing failure activity.status: "error"(preserves binding for recovery).status: "stopped"to avoid creating a synthetic session without a backingProviderServicedirectory entry.Both paths set
lastErrorso the client can detect the failure.Single-file production change in
ProviderCommandReactor.ts. Four regression tests added covering existing-session, null-session, stopped-session failure paths, and recovery after a provider-switch error.Why
After the client dispatches
thread.turn.start, the HTTP call succeeds soturnStartSucceeded = true. The client then waits for a server-side signal viahasServerAcknowledgedLocalDispatch, which checks forphase === "running",threadError, or a session snapshot change.When
sendTurnfails server-side, the existing handler only appended a failure activity — it never updated the session. If the session was already bound and unchanged, none of the acknowledgment conditions were met:phasestayed"ready",threadErrorwasnull, and the session snapshot was identical. This leftisSendBusypermanently stuck, the send button disabled, and "Working for …" hanging untilCmd+R.Previous attempts to fix this (#1348, #1393, #1542) added client-side workarounds. This change addresses the root cause on the server by ensuring the session always transitions to a detectable state on failure.
Validation
bun fmt— cleanbun lint— cleanProviderCommandReactortests pass (4 new)Checklist
Note
Medium Risk
Changes error-handling in
ProviderCommandReactorto mutate persisted session state on turn-start failures, which can affect client behavior and session reuse/recovery paths. Covered by new regression tests across existing-session and no-session scenarios, reducing risk but still touching orchestration state transitions.Overview
Ensures
thread.turn-start-requestedfailures no longer only append aprovider.turn.start.failedactivity: the reactor now also callssetThreadSessionto move the thread session into a detectable terminal state and populatelastError.On failure, sessions with an existing non-
stoppedbinding are markedstatus: "error"(preserving binding for recovery), while cases with no real binding (including previouslystoppedsessions) are markedstatus: "stopped"to avoid creating a synthetic bound session. Tests are updated/added to assert these statuses,lastError, and that a subsequent correct-provider turn can recover after a provider-switch failure.Reviewed by Cursor Bugbot for commit aee8e69. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Set thread session to error state when
sendTurnfails inProviderCommandReactorthread.turn.startfails, the reactor now updates the thread session: if an active session existed it transitions tostatus: 'error', otherwise it creates/updates a session withstatus: 'stopped'.activeTurnIdis cleared andlastErroris set to'Provider turn start failed: …', alongside the existingprovider.turn.start.failedactivity.ProviderCommandReactor.test.tscover the error, stopped, and recovery scenarios.Macroscope summarized aee8e69.