Repository navigation
fix(web): desktop window recovers when its backend restarts during a renderer reload - #26612
juliusmarminge wants to merge 4 commits into
Conversation
…reachable backend The session request fails with a transport error (no HTTP response) on the first attempt, as fetch does while the backend is still restarting. resolveInitialServerAuthGateState() should retry within the bootstrap budget and resolve; on main it rejects with PrimaryEnvironmentRequestError (HTTP 500). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tarts A renderer reload while the local backend was down showed the fatal "fetch-session-state (HTTP 500)" screen on the first connection-refused attempt. fromCause reports a transport failure with no response as status 500, so the bootstrap retry never saw it as transient. Treat a wrapped HttpClientError TransportError as transient; real HTTP 500 responses still fail fast. Fixes #26604 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ighbours Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Wrapped transport failures now use the existing bounded bootstrap retry mechanism, allowing recovery when the backend restarts. Authentication requirements and retry limits remain unchanged. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Classify and test transport retries apps/web/src/environments/primary/auth.ts, apps/web/test/environmentHttpTest.ts, apps/web/src/authBootstrap.test.ts |
The transient-error check recognizes wrapped HttpClientError transport failures. The HTTP test helper returns its runtime-backed runner, and the regression test verifies authentication after an initial transport failure. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Possibly related issues
pingdotgg/t3code#23378— Reports a similar bootstrap failure when the backend is unavailable. This change adds retry handling for wrapped transport errors.pingdotgg/t3code#26162— Reports a first-open bootstrap failure during backend startup. This change addresses a related retry path, though the issue describes a different IPC error wrapper.
Possibly related PRs
- pingdotgg/t3code#25526 — Both changes add retry handling to authentication-related requests during temporary unavailability.
- pingdotgg/t3code#21780 — Both changes address desktop startup while the local backend is unavailable.
Suggested labels: bugfix, size:S
Suggested reviewers: t3dotgg, maria-rcks
Merge Risk: 
Minimal · up to 9176d
-
Desktop bootstrap retries transport failures; no merge-blocking risk is evident.
Pre-merge checks: 
4
-
Full details: Description check
-
Explanation
The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the failure, the retry logic change, issue scope, focused tests, desktop validation, limitations, and agent details.
Full details: Linked Issues check
-
Explanation
For directly linked issue
#26604, the change makes a wrappedPrimaryEnvironmentRequestErrortransient when its cause is anHttpClientErrorwithTransportError. It preserves immediate failure for real HTTP 500 responses because the new condition checks the cause type and reason. The addedauthBootstrap.test.tstest covers an unreachable backend followed by recovery and verifies authenticated bootstrap. The separate macOS process-coalition problem is explicitly outside this PR's stated scope.
Full details: Out of Scope Changes check
-
Explanation
The changes are limited to bootstrap retry classification and supporting test infrastructure. The added test helper return value supports the new retry test. No unrelated product behavior or native process-spawn changes are included.
-
Finishing Touches
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
Problem
When the desktop's renderer and local backend are killed together while the Electron main process survives, the window reloads after 500 ms and lands on a fatal "Primary environment request failed during fetch-session-state (HTTP 500)" screen. It stays there until the user clicks Reload, even though the backend is back a few seconds later. On macOS this happens when the user force-quits an app an agent launched. To reproduce on Linux, send SIGTERM to the renderer, GPU and network helpers and the backend child. The window is still on the error screen 30 s later, and the backend was ready again after 3.5 s.
Change
The auth bootstrap already retries for 15 s, and
isTransientBootstrapErroralready meant to retry fetch failures through itsTypeErrorbranch. That branch never fires:fetchSessionStateandexchangeBootstrapCredentialwrap every failure in aPrimaryEnvironmentRequestErrorinside the retried operation, andfromCausemaps a transport failure with no response to status 500. 500 is not in {502, 503, 504}, so the first refused connection was fatal.isTransientBootstrapErrornow also treats aPrimaryEnvironmentRequestErroras transient when its cause is anHttpClientErrorwhose reason isTransportError(no HTTP response). A real HTTP 500 response still fails at once. The retry budget, the status reported byfromCauseand the other callers do not change.Scope and approval
Fixes #26604
This PR fixes the second half of the issue: the reloaded window never retries. The first half is macOS attributing an agent-launched app to T3 Code's process coalition, so force-quitting that app kills the renderer and backend. That needs native spawn changes and is not part of this PR.
Verification
vp test run src/authBootstrap.test.ts src/environments/primary/(apps/web): 3 files, 17 tests pass. The new testresolveInitialServerAuthGateState > retries the desktop bootstrap while the backend is still unreachablefails on main with the reported chain:PrimaryEnvironmentRequestError … fetch-session-state (HTTP 500), caused byHttpClientError: Transport error, caused byTypeError: Failed to fetch.vp run check:changed: format, lint, knip, typecheck and tests all pass.vp run build:desktop) under Xvfb, fresh T3 home, the same driver on both sides. The driver sends SIGTERM to the renderer, GPU and network helpers and the backend child, which are all descendants of the Electron main PID captured at spawn. Main survives. It records snapshots and DOM text over CDP at +2, +8, +20 and +30 s.Timelines: before-886d8f6812-timeline.txt, after-3866aa31f3-timeline.txt. Driver: drive.sh, cdp-text.mjs.
Not checked: macOS itself. The coalition kill that triggers this cannot run on Linux. The fixed code path is platform-independent, and this run reproduced it with the same set of killed processes.
Model and harness: Claude Opus 5.5 (claude-opus-5-5) in Claude Code via T3 Code, with Codex gpt-6.1-sol reviewers.
🤖 Generated with Claude Code