fix(server): failed updates report download diagnostics#33239
Problem
Closes #33233. When a service-managed server update fails to download a release asset, the client only receives Could not prepare t3@<version>. The installer knows which download failed, but the update error drops that context, including the HTTP status.
Change
Record the HTTP status and download host as structured installer-error fields, then include them and the failed install step in the existing server-update error. Preserve the underlying cause and the existing preflight-blocked and missing-mirror-release messages. Only the host is exposed; credentials, URL paths, query parameters, and response bodies stay out of the message.
The existing RPC error carries the result to web, desktop, and mobile; no client or wire-schema change is needed.
Scope and approval
This qualifies as a very small, focused fix for an obvious bug under CONTRIBUTING.md: it restores diagnostic context already available at the failing download, with no change to installation, retry policy, or update handoff behavior.
Verification
Head 53d9b7c289 (PR plus current main), compared with main 4c361199f4.
selfUpdate.test.ts: 15 passed. The new HTTP rows (checksums 504 and 403, archive 503) fail on main and check host-only output, cleanup, no launcher handoff, and a successful retry.vp run check:changed: format, lint, knip, graphql, typecheck (3 packages) and tests (3 files, 35 passed) all pass.- Two independent review rounds: both MERGE.
Evidence
Server rows run the real ServerSelfUpdate and pinned-runtime code from each checkout, with an injected HttpClient and Effect TestClock (service harness, not a live update). The same driver runs on both sides.
| Row | Before (4c361199f4) | After (53d9b7c289) | Transcript |
|---|---|---|---|
| Checksums HTTP 504 | Could not prepare t3@1.1.0. | Could not prepare t3@1.1.0 while downloading the t3 release checksums (HTTP 504 from cdn.example). | S1-transcript.md |
| Download timeout (60 s) | Could not prepare t3@1.1.0. | Could not prepare t3@1.1.0 while downloading the t3 release checksums (timed out) (from github.com). | S4-transcript.md |
| Checksum mismatch | Could not prepare t3@1.1.0. | Could not prepare t3@1.1.0 while verifying the t3 release archive checksum. | S5-transcript.md |
On both sides every failure leaves empty staging and makes no process or launcher calls.
Web, 390×844 dark. This runs the real dev app with a labelled client-state harness that injects each revision's captured service error. Environment: Chrome 157 on Linux, DPR 2, no device emulation, 100% font scale, frozen Date. The recording steps are: error toast at 0 s, Copy error at ~2.3 s, close toast at ~5.1 s, hover the truncated Settings row at ~6.7 s, then the full tooltip.
| Recording | Before | After |
|---|---|---|
| Toast → copy → tooltip | C2-before.mp4 | C2-after.mp4 |
| Tooltip, 390×844 dark | Before 4c361199f4 | After 53d9b7c289 | Diff0 | DiffT (>3/255) |
|---|---|---|---|---|
| Full reason revealed | C2-before-tooltip.png | C2-after-tooltip.png | C2-tooltip-diff0.png | C2-tooltip-diffT3.png |
What else changed:
- The message grows from 49 to 207 characters. The toast reaches its existing four-line clamp, and its copy control moves down with it; copy still writes the full text.
- The Settings row keeps the same truncated prefix. Its tooltip grows and moves up to stay anchored above the row.
- At zero threshold, pixel differences fall only inside the tooltip and its shadow (x 130–769, y 101–299); nothing changes outside it.
Rebuild: runtime-driver.mjs, client-state-driver.js, browser-workflow.md, raw-evidence.zip, full evidence index, fixture matrix. A rebuild of the server rows with the uploaded driver matched byte for byte.
Not exercised: a live service-managed update and restart, real mirror networking, and native clients. The native clients render the same reason string through an unchanged path.
AI-assisted; verified with the tests and tools listed above.
Fixes pingdotgg/t3code#33233
Checks
Added 1 commit
- fix(server): failed updates report download diagnosticsd49e8ee
Approvability
Verdict: Approved at d49e8ee
Macroscope's review found this PR approvable — Failed server updates now report the preparation step and available HTTP status and download host. This is a diagnostics-only change; download and update activation behavior remain unchanged.
You can add or adjust custom eligibility rules. Learn more.
No actionable comments were generated in the recent review.
Walkthrough
-
Release asset failures now retain HTTP status and download-host details. Generic self-update preparation errors include the failed step and available download details. Tests cover HTTP 504, 503, and 403 failures, cleanup, and successful retry.
Changes: Self-update download diagnostics
Layer / File(s) Summary Capture and surface download details
apps/server/src/cloud/pinnedRuntime.ts,apps/server/src/cloud/selfUpdate.tsRelease asset errors record the HTTP status and host when available. Generic preparation errors include the failed step and available download details. Test download failures and retry
apps/server/src/cloud/selfUpdate.test.tsParameterized tests check error details for checksum and archive download failures, verify cleanup, and confirm retry succeeds after the simulated failure is disabled. Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Possibly related issues
- pingdotgg/t3code issue 32896 — The download diagnostic path overlaps, but this change does not address the stale update offer or rejection message.
- pingdotgg/t3code issue 21922 — The download error path overlaps, but this change does not address the
HTTPS_PROXYbehavior or theECONNRESETcause.
Possibly related PRs
- pingdotgg/t3code#29911 — It changes the same self-update error classification and message path.
Suggested labels:
bugfix,size:SSuggested reviewers:
juliusmarminge,t3dotgg
Merge Risk: External image Minimal · up to d49e8
-
No actionable issue in the update diagnostics remains identified; the change is mergeable after normal checks.
Pre-merge checks: Passed 4
-
Check name Status Explanation Title check Passed The title "fix(server): failed updates report download diagnostics" matches the main change. The changeset adds HTTP status and download host fields to PinnedRuntimeInstallError and includes the faile… Linked Issues check Passed Directly linked issue #33233has these coding objectives: (1) the server self-update error names the failed install step; (2) the error includes the HTTP status and download host when a release downlo…Out of Scope Changes check Passed All changed production code is connected to #33233. The changes are in apps/server/src/cloud/pinnedRuntime.ts (error fields and population in fetchReleaseAsset), apps/server/src/cloud/selfUpdate.ts (e…Description check Passed The description includes the required Problem, Change, Scope and approval, and Verification sections. It explains the bug, the fix, why the focused change qualifies without prior approval, and the tes… Full details: Title check
-
Explanation
The title "fix(server): failed updates report download diagnostics" matches the main change. The changeset adds HTTP status and download host fields to PinnedRuntimeInstallError and includes the failed install step and these details in the server self-update error. The title is short, uses a conventional commit prefix, and avoids vague terms.
Full details: Linked Issues check
-
Explanation
Directly linked issue
#33233has these coding objectives: (1) the server self-update error names the failed install step; (2) the error includes the HTTP status and download host when a release download fails; (3) the underlying cause is preserved. Source diff (merge base c6ca6056 to head d49e8ee0):- Objectives (1) and (2): apps/server/src/cloud/pinnedRuntime.ts adds optional httpStatus and downloadHost fields to PinnedRuntimeInstallError. fetchReleaseAsset fills httpStatus from HttpClientError StatusCodeError responses and downloadHost from the request URL (falling back to the supplied URL). apps/server/src/cloud/selfUpdate.ts maps generic prepare failures to "Could not prepare t3@<version> while <step> (HTTP <status> from <host>)."
- Objective (3): the error passes the original cause to failWith, so the cause chain is kept.
- Only the host is exposed. The message does not include the URL path, query, or response body.
- Preflight-blocked and unpublished-mirror-release messages keep their existing branches.
The issue also suggests marking transient HTTP failures as retryable ("and/or"). The PR does not do this. The PR description states that retry policy is unchanged. The issue wording allows this choice, so it is not a failing requirement.
The test changes described in the summary cover HTTP 504/403 checksum failures and HTTP 503 archive failures, host-only diagnostics, staging cleanup, and retry. I did not read the test diff directly. This assessment relies on the summary for test coverage.
Full details: Out of Scope Changes check
-
Explanation
All changed production code is connected to
#33233. The changes are in apps/server/src/cloud/pinnedRuntime.ts (error fields and population in fetchReleaseAsset), apps/server/src/cloud/selfUpdate.ts (error message composition), and apps/server/src/cloud/selfUpdate.test.ts (regression tests and a test harness that accepts a custom HTTP client and returns the temporary base directory). The harness change supports the new tests. No change touches installation, retry policy, update handoff, or client or wire schemas, as the PR description states. The four pruning-test failures mentioned in the PR description are reported as environmental Windows EPERM results. They are not part of this diff. The test diff was not read directly, so test-only changes are assessed from the summary.
Full details: Description check
-
Explanation
The description includes the required Problem, Change, Scope and approval, and Verification sections. It explains the bug, the fix, why the focused change qualifies without prior approval, and the tests and limitations reported.
-
Finishing Touches
-
Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
External image Recent review info
-
External image Run configuration
-
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: main
- File: .coderabbit.config.ts
- Commit: c6ca605
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Advanced
- Run ID:
e32aa91b-b691-4785-883b-cfdca1c375c9
External image Commits
-
Reviewing files that changed from the base of the PR and between c6ca6056309904f89b90b6055d797973be0a0939 and d49e8ee0f13114789f7c7a43480f1d0b51626259.
External image Files selected for processing: 3
-
apps/server/src/cloud/pinnedRuntime.tsapps/server/src/cloud/selfUpdate.test.tsapps/server/src/cloud/selfUpdate.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
External image Recent review info
-
External image Run configuration
-
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: main
- File: .coderabbit.config.ts
- Commit: c6ca605
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Advanced
- Run ID:
e32aa91b-b691-4785-883b-cfdca1c375c9
External image Commits
-
Reviewing files that changed from the base of the PR and between c6ca6056309904f89b90b6055d797973be0a0939 and d49e8ee0f13114789f7c7a43480f1d0b51626259.
External image Files selected for processing: 3
-
apps/server/src/cloud/pinnedRuntime.tsapps/server/src/cloud/selfUpdate.test.tsapps/server/src/cloud/selfUpdate.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
-
Added 1 commit
- Merge remote-tracking branch 'origin/main' into pr-3323953d9b7c