Repository navigation
Closed
Labels
via-triageFiled through npx t3 triageFiled through npx t3 triage
Description
What happened
A Windows desktop app (Nightly) updated a remote macOS server (background service) to the newest nightly. The update succeeded and the server restarted on the new version. The desktop app kept showing the server update. Clicking it again failed twice with:
Server update failed: Remote updates must select a newer server version.
Reloading the window (F5) made the update offer go away.
Diagnosis
- The server log shows the handoff to 0.1.8-nightly.20261108.4353 at 10:47:09 and a restart on that version at 10:47:12. The npm
nightlytag points to the same version, so no newer server build exists. - Both later
server.updateServerWithProgresscalls (10:47:22 and 10:49:23, same client trace) end inServiceLauncherRejectedError. The launcher's#handleUpdateRequestrejects whencompareExactServiceVersions(targetVersion, child.version) <= 0. Each call took about 300 ms because the target runtime was already on disk, which means the target was the version already running. - On the client,
collectServerUpdateTargets(apps/web/src/components/sidebar/updateEverything.logic.ts) picks servers byresolveVersionMismatch(config.environment.serverVersion, targetVersion). After the restart and reconnect, the client still holds the oldserverVersion(0.1.8-nightly.20261107.4340) for that environment, so it still lists the server as a target for 4353. The cached config is only refreshed by a full reload. - The client also has no special handling for this rejection. It shows a generic error even though the server is already on the requested version.
main(8e6a732) has no changes to these files since v0.1.8-nightly.20261107.4340.
Steps to reproduce
- Run a remote server as the background service (
t3 service install) on nightly N-1. - Connect from the desktop app (Nightly) while nightly N is available.
- Start the server update from the desktop app's update capsule / "Update all". Wait for it to succeed and reconnect.
- The server update is still offered. Click it again: the error is "Remote updates must select a newer server version."
- Reload the window: the offer is gone.
Version
- Desktop app (client, where the stale state lives): T3CodeNightly 0.1.8-nightly.20261107.4340 on Windows
- Server: updated from 0.1.8-nightly.20261107.4340 to 0.1.8-nightly.20261108.4353 (background service, macOS)
- Service launcher process: 0.1.1-nightly.20261016.3203
- Triage CLI: 0.1.1-nightly.20261016.3203 (only the CLI that ran
t3 triage)
Environment
- Server: macOS 27.2 (darwin arm64), Node v26.8.2, launchd service, behind a LAN reverse proxy
- Client: T3 Code Nightly desktop app on Windows 10/11 x64 (Electron 44.10.1)
Evidence
Server trace (`server.trace.ndjson`), `cloud.server_self_update.update` spans:
10:43:08–10:44:13 4x Failure Could not prepare t3@0.1.8-nightly.20261108.4353 (PinnedRuntimeInstallError while downloading the t3 release checksums; cause not logged, likely unrelated)
10:46:43 Success (26 s, download + handoff)
10:47:22 Failure ServiceLauncherRejectedError: Remote updates must select a newer server version. (296 ms)
10:49:23 Failure ServiceLauncherRejectedError: Remote updates must select a newer server version. (306 ms)
Service log:
[10:47:09.719] INFO: Server update prepared; handing off to the service launcher.
targetVersion: '0.1.8-nightly.20261108.4353'
[10:47:12.823] INFO: Listening on http://0.0.0.0:3773
`/.well-known/t3/environment` afterwards: `serverVersion: 0.1.8-nightly.20261108.4353`, `serverSelfUpdate: boot-service`.Related issues
- [Bug]: Client shows a server update as "Restarting…" for 32 minutes when the host comes back without an update outcome #27130 (client shows "Restarting…" when the host comes back without an update outcome): also client-side update state after a server restart
- [Bug]: Settings › About › Install updates only the desktop app; the background service it is paired with stays on the old version #31506 (About › Install updates only the desktop app)
Fix applied or workaround
Reload the desktop app window (Ctrl+R / F5) after a server update.
Filed by
Triaged with Claude Code (Claude Opus 5.5, claude-opus-5-5) via t3 triage.
Metadata
Metadata
Assignees
Labels
via-triageFiled through npx t3 triageFiled through npx t3 triage
Activity
juliusmarminge commentedon Nov 8, 2026
Tried to reproduce this on current main (8e6a732) and could not trigger it yet.
Setup: a real service launcher running the published
t3@0.1.8-nightly.20261107.4340Linux runtime (serverSelfUpdate: boot-service), paired as a remote environment to a client whose app version was0.1.8-nightly.20261108.4353.serverVersionwithout a reload.Before the update succeeded, I also hit your first failure mode: GitHub returned 504 on the 4353
SHA256SUMS/archive, giving "Could not prepare t3@…".The path I could not drive is the desktop app's sidebar update capsule while a desktop update is pending. That is where
localUpdateVersionbecomes the target. To narrow it down:SeoFood commentedon Nov 8, 2026
Thanks for digging in. Answers, plus a correction to my original diagnosis:
localUpdateVersionis 4353, because the app itself was 4340.Correction: the stale
serverVersionexplanation in the issue is probably wrong. The server trace shows the client reconnecting at 10:47:13, after the restart onto 4353 at 10:47:12. On reconnect it ranws.loadServerConfigandsubscribeServerConfigagainst the new server, before the first rejected call at 10:47:22. So the client should have had the new config. Also, the trace ID I called "the same client trace" is the server process's trace, not the client's.Server-side timeline (
cloud.server_self_update.update): 4× "Could not prepare" (10:43:08–10:44:13). Success at 10:46:43, then handoff and restart. Then three rejections, not two: 10:47:22, 10:49:23, 10:51:33. Each one was "Remote updates must select a newer server version" and took ~300 ms. After that came the reload (reconnect at 10:52:03).A likely path in the code (
apps/web/src/components/sidebar/updateEverythingRun.tsxat v0.1.8-nightly.20261107.4340, unchanged onmain):retryFailedUpdateRunServersre-sends theServerUpdateTargetstored in the run (machine.server). It does not compare the target against the server's currentserverVersion."updated"as a failure ("Could not start the update"). This includes"skipped", which is what an interrupted command returns. When that happens,machine.serverstays set, so the capsule keeps offering Retry. The main path treats"skipped"as not failed.run.localVersion !== null, socloseFinishedUpdateRunnever clears the run. The capsule stays until the in-memory run atom is lost, which is why F5 fixed it.I couldn't tell from the server side why the client didn't record the 10:46:43 retry as
"updated", even though the server says it succeeded. Two possible fixes: have Retry drop targets the server already satisfies, and have the client treat "must select a newer server version" as "already up to date" whenserverVersion >= targetVersion.Server environment, if useful: service launcher process is
0.1.1-nightly.20261016.3203(it supports the prepared/committed trial protocol), child0.1.8-nightly.20261108.4353, macOS 27.2 arm64.Triaged with Claude Code (Claude Opus 5.5, claude-opus-5-5) via
t3 triage.letuwang commentedon Nov 11, 2026
Note
🤖 Claude Opus 5.5 (via
t3 triage) responding on behalf of letuwangAnother occurrence through the sidebar capsule's Retry button. This time the first failure was different, and the server was updated by hand rather than by the app.
nightly).cloud.server_self_update.update): at 11:54 and 12:00 (local), updates from 0.1.9-nightly.20261111.4501 failed with "installed service launcher speaks protocol 3, but t3@0.1.10-nightly.20261111.4529 requires protocol 4". The user then installed 4529 by hand. At 12:08:25, 12:08:41 and 13:42:48, Retry requested 4529 again. Each request was rejected in ~500 ms withServiceLauncherRejectedError: Remote updates must select a newer server version.cloud.pinned_runtime.ensure_installedagainst a runtime already on disk, so the target was the version already running.This supports the
retryFailedUpdateRunServerstheory (apps/web/src/components/sidebar/updateEverythingRun.tsx, unchanged onmain). It re-sends the storedmachine.servertarget without comparing it to the server's currentserverVersion. A successful in-app update isn't needed to trigger this: any failed run followed by an out-of-band update leaves a Retry that can never succeed.Suggested fix, unchanged: drop retry targets whose server already satisfies
targetVersion, and treat this rejection as "already up to date" whenserverVersion >= targetVersion. Workaround: reload the window.