[Bug]: `t3 service install` fails on WSL2 — `loginctl enable-linger` is called with no username and cannot resolve a session
Nobody has claimed this yet.
- 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
On Ubuntu under WSL2:
npm install -g t3@latestt3 service install
Install fails at the final activation step and rolls back.
The rollback itself is clean — no dangling unit is left in ~/.config/systemd/user/, and t3 service status correctly reports not installed. That part works exactly as the code comments describe.
Expected behavior
The systemd user unit is installed, enabled and started, as it is on non-WSL Linux.
Lingering is not actually the obstacle here: on this machine Linger=yes was already set for the user (loginctl show-user $(id -un) → Linger=yes), so the step is a no-op that fails purely on argument resolution.
Actual behavior
BootServiceCommandError: Background setup failed while enabling lingering for this user (exit code 1).
Root cause. install runs loginctl enable-linger with no username argument:
https://github.com/pingdotgg/t3code/blob/main/apps/server/src/cloud/bootService.ts#L346
yield* runStep("enabling lingering for this user", "loginctl", ["enable-linger"]);
The comment above it explains the reasoning:
No username argument: loginctl defaults to the calling user, which is always right, while
$USERcan be stale (su without -l) or unset.
That assumption does not hold under WSL2. XDG_SESSION_ID is unset in a normal WSL2 shell, so logind cannot resolve a session for the caller and the no-arg form fails, while the explicit form succeeds:
$ loginctl enable-linger $(id -un)
$ echo $?
0
$ loginctl enable-linger
Could not enable linger: No such device or address
$ echo $?
1
Note this is not a "systemd is missing" case — systemctl --user is-system-running returns running, and daemon-reload / enable / start all succeed. Only the no-arg enable-linger fails.
Suggested fix
Pass the resolved username explicitly rather than relying on the caller-default:
yield* runStep("enabling lingering for this user", "loginctl", ["enable-linger", os.userInfo().username]);
os.userInfo().username comes from the passwd database for the effective uid, so it avoids the stale/unset $USER problem the current comment is guarding against while also working when there is no logind session.
Alternatively, treat a failing enable-linger as non-fatal when lingering is already enabled (check loginctl show-user <user> for Linger=yes first), since in that case the step has nothing to do.
Impact
Major degradation or frequent failure
(t3 service install and t3 service update are unusable on WSL2 without a workaround. Everything else works well — see Workaround.)
Version or commit
t3@0.0.31
Environment
Ubuntu on WSL2 (kernel 6.18.33.2-microsoft-standard-WSL2), Windows host, node v22.22.1, npm 10.9.4, systemd user manager running, Linger=yes already set.
Logs or stack traces
$ t3 service install
[20:27:02.062] ERROR (#5): BootServiceCommandError: Background setup failed while enabling lingering for this user (exit code 1).
at .../t3/dist/bin.mjs:17006:71
at cloud.boot_service.run_step (.../t3/dist/bin.mjs:17062:11)
at cloud.boot_service.install (.../t3/dist/bin.mjs:17065:17)
at cli.service.reconcile (.../t3/dist/bin.mjs:19594:24)
at cli.service.run (.../t3/dist/bin.mjs:19593:196)
$ t3 service status
T3 Code service
Status: not installed
Next: Run `t3 service install`.
Workaround
Shim only the one call, for the duration of the install:
mkdir -p /tmp/t3-linger-shim
REAL=$(command -v loginctl)
cat > /tmp/t3-linger-shim/loginctl <<EOF
#!/usr/bin/env bash
if [ "\$1" = "enable-linger" ] && [ \$# -eq 1 ]; then
exec "$REAL" enable-linger "\$(id -un)"
fi
exec "$REAL" "\$@"
EOF
chmod +x /tmp/t3-linger-shim/loginctl
PATH="/tmp/t3-linger-shim:$PATH" t3 service install
With that, the install completes normally and the service is healthy on WSL2:
$ t3 service status
T3 Code service
Status: installed · t3@0.0.31
Unit: /home/<user>/.config/systemd/user/t3code.service
$ systemctl --user is-active t3code
active
$ ss -ltnH 'sport = :3773'
LISTEN 0 511 127.0.0.1:3773 0.0.0.0:*
Cold start was ~3s with the data dir on ext4, and Claude Code / Codex / Grok providers were all detected correctly afterwards.
Happy to open a PR with the one-line change if that is welcome — I saw the note in the README that small fixes may be considered.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in apps/server/src/cloud/bootService.ts around line 346 and inspect the install flow's lingering step. Reproduce with t3 service install under WSL2, then verify the change using the explicit username behavior described in the issue. Done means installation completes and t3 service status reports the service as installed and healthy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux, typescript
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100