pingdotgg / pingdotgg/t3code

[Bug]: macOS `t3 service install` reports "already installed" while launchd still runs the previous launcher

Open Beginner friendly
#12,197 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accepted bug via-triage
Dominant language
TypeScript
Stars
23k
Forks
5.9k
Avg merge
11h 14m
Merged PRs (30d)
357

Description

Before submitting
  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.
Area

apps/server

Steps to reproduce

macOS 15, background service already installed from an older release.

  1. npx t3@nightly service install → fails with Background setup failed while starting the service (exit code 5) (that step is #11995: the old job survives bootout --wait, so bootstrap gets EIO).
  2. npx t3@nightly service install again.
Expected behavior

The retry repairs the service, or reports that it is not running the installed version.

Actual behavior

The retry prints T3 Code service is already installed with t3@0.0.43-nightly.20260917.1837. and exits 0 without touching launchd. Disk says the new version; launchd still runs the old one:

$ grep -A1 ProgramArguments ~/Library/LaunchAgents/com.t3tools.t3code.service.plist | tail -1
    <string>/Users/me/.t3/runtime/versions/0.0.43-nightly.20260917.1837/t3</string>
$ launchctl print gui/501/com.t3tools.t3code.service | grep -A2 arguments
	arguments = {
		/Users/me/.nvm/versions/node/v22.22.1/bin/node
		/Users/me/.t3/runtime/service-launcher.mjs

Every remote "Update server" then keeps failing with This release requires a newer T3 Code service launcher. Update it on the server machine. (#11940), and the command that message points to says everything is fine. Only a reboot or a manual launchctl bootout + bootstrap breaks the loop.

Cause

BootService.status on launchd compares only the unit file, runtime sentinel, and service-state.json against the CLI version (apps/server/src/cloud/bootService.ts, status). A failed bootstrap leaves no trace, so current is true and reconcileService short-circuits. systemd gets service-stopped from readSystemdProblems; launchd has no equivalent.

Suggested fix

Write the existing .restart-pending marker before the unit write on every install, not only for start: false. A successful activate already removes it, and the launcher removes it when it comes up on the awaited version. A failed bootstrap then leaves the marker, status reports restart-pending, and the retry re-runs stop/start. Together with the bootout fix for #11995 the retry actually replaces the old job. Two-line change; I can open a PR.

Related
  • #11995 / PR #12005: bootout --wait exits 64 on macOS 15, so bootstrap fails with EIO. That is step 1 above; this issue is the retry after it.
  • #11934, #12020, PR #11940: the protocol gate that blocks remote updates under a pre-#11510 launcher. Correct behavior, but it sends users to service install, which then lies.
  • PR #7874: an earlier attempt at the same bootout wait, closed as believed fixed.
Impact

Major degradation or frequent failure

Version or commit

t3@0.0.43-nightly.20260917.1837, main 6d1d549441

Environment

macOS 15.7.4 (24G517), Apple Silicon, service installed with npx t3@nightly service install, remote updates from the desktop client

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/server/src/cloud/bootService.ts, especially BootService.status and reconcileService, and trace how service-state.json and the .restart-pending marker affect installation retries. Reproduce the macOS launchd scenario from the issue, then verify that a failed bootstrap is detected and a subsequent service install retries reconciliation instead of reporting the old launcher as current.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, node.js, typescript
Domain
devops, operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.