Skip to content

[Bug]: t3-code running as service reports not connected - have to re-pair #13072

Description

@hades200082

Before submitting

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

Area

Not sure

Steps to reproduce

  1. Run t3-code as a service on a remote machine with npx command (nightly version)
  2. Run t3-code locally with npx command (nightly version)
  3. Pair remote to local via tailscale
  4. Use the remote instance daily from local workstration
  5. Update remote service via npx command periodically (nightly version)

After a while, the remote becomes unable to connect locally. Re-pairing is the only way I've found to resolve it - but it keeps happening and I'm not always in a position to SSH into the server to re-pair.

Also, every so often the update server option in the local t3-code UI is unable to update the server too.

Expected behavior

I'd expect it to be stable and able to connect remotely, update remotely, etc. and not log in to find that I can't do any work because the server un-paired again.

Actual behavior

After a while, the remote becomes unable to connect locally. Re-pairing is the only way I've found to resolve it - but it keeps happening and I'm not always in a position to SSH into the server to re-pair.

Impact

Major degradation or frequent failure

Version or commit

all nightly versions for the last month

Environment

Ubuntu 24 on server, Linux Mint on local workstation

Logs or stack traces

Screenshots, recordings, or supporting files

No response

Workaround

Re-pairing the remote is the only way I've found so far

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 22, 2026
  2. juliusmarminge commented on Sep 22, 2026

    @juliusmarminge
    Member

    Triage

    Two separate things are in this report, and neither is a new bug we can confirm from what's here. There is no version string, no Update error text, and no server log. A service restart does not by itself revoke a pairing session.

    Re-pair

    Pairing-issued bearer sessions last 30 days from issue, and use does not extend them.

    • DEFAULT_SESSION_TTL is Duration.days(30) in apps/server/src/auth/SessionStore.ts. Neither pairing redemption path passes a session TTL. Direct Tailscale clients store that bearer and reuse it.
    • markConnected updates last_connected_at only. Nothing writes a new expires_at.
    • The signed token carries an absolute exp. When it is past, verification fails with SessionTokenExpiredError.
    • The client treats invalid_credential as a blocked authentication error (The environment credential is invalid.), not as a retry. Recovery is a new pairing link from the host (t3 pair / t3 pair --tailscale), which is why this needs SSH.

    That is the behavior in #13055 and the direct-client half of #9884. Those stay the right issues for "make this configurable or sliding" and "should a direct client stay paired until revoke." This report is not a duplicate of either: it says the drop follows periodic npx updates of a service, and it also says in-app Update fails.

    A restart of a healthy service does not rotate secrets/server-signing-key.bin or clear auth_sessions. Both live under the T3 home (~/.t3/userdata unless T3CODE_HOME / --base-dir is set). Re-pair after every npx update would be a different bug, and this report doesn't show it. The Settings row says Not connected only when the saved environment is idle. An expired session says Connection failed with the credential error. A dead service says Reconnecting or Offline.

    Update server

    In-app Update only works when the server is the background service (serverSelfUpdate: "boot-service"). Children ask the existing launcher to switch runtimes. They never replace the unit or the launcher. That is why a layout change has to be installed on the host.

    Since #11510 (2026-09-13) the unit runs ~/.t3/runtime/versions/<version>/t3 __service-launcher. Older launchers still look for node_modules/t3/dist/bin.mjs and reject every newer archive with The requested target runtime is missing or incomplete. That is #11934, closed by #11940. Current nightlies fail that case earlier, in runServicePreflight, with: This release requires a newer T3 Code service launcher. Update it on the server machine. The button cannot fix that. On the server, as the service user:

    npx t3@nightly update --yes
    t3 service status
    systemctl --user cat t3code.service

    --yes matters over SSH. Without a terminal, t3 update does not restart the service; it leaves .restart-pending and the old process running. t3 service update is not the update command. It is a deprecated alias of t3 service install.

    A systemd drop-in that still sets ExecStart= to service-launcher.mjs keeps the old launcher even after the base unit is rewritten. That showed up on #11934: the update command logged success, systemd hit the start limit, and nothing was listening. Re-pair does not help until the service is listening again. After it is, the old session should still work unless expires_at has passed.

    If this host is not the background service, and the unit is npx t3@nightly serve ..., there is no Update button. The client offers Copy update command, and that command is npx t3@<client-version> with no subcommand. Bare t3 starts another server. It does not upgrade a running service, and it fails if the port is already taken. Stop the service and start the same serve flags on the version in the notice, or install the real service with t3 service install and then use t3 update.

    What would move this

    Please paste, with home paths and tokens removed:

    1. The exact Update / Connection failed text.
    2. t3 service status, and systemctl --user cat t3code.service if this is Linux.
    3. The version lines from the client and from the server log around one failure (~/.t3/userdata/logs/server.log and boot-service.log).
    4. For the session that stopped working: issued_at, expires_at, and last_connected_at only. If expires_at was still in the future, this is not Allow configuring session lifetime (or sliding expiry) for pairing-issued sessions instead of a fixed 30-day TTL #13055.

    If the Update text is the missing-runtime or old-launcher message, that half is #11934 and a host t3 update --yes is the fix. If the session row was already expired, the re-pair half belongs on #13055.

  3. added
    needs more infoInitial triage showed no bug. Awaiting more info
    via-triageFiled through npx t3 triage
    and removed
    needs-triageIssue needs maintainer review and initial categorization.
    bugSomething is broken or behaving incorrectly.
    on Sep 22, 2026
  4. kcazin commented on Oct 8, 2026

    @kcazin

    A likely cause for the "update server option … is unable to update the server" part of this report: connections paired before #9786 (granular permissions, first in nightly 2761) keep a bearer session with the old five scopes, which don't include environment:maintain. Once the server is on 2761 or later, the client's update buttons are gated on that permission. The composer button is disabled with no reason, and Settings → Connections → "Update all" stays enabled but returns without sending anything. Full diagnosis, source references and repro in #17034. Workaround: re-pair with a fresh t3 pair / t3 auth pairing create link, or run npx t3@nightly update on the server.

    Environment for this occurrence: macOS desktop 0.0.46-nightly.20261007.2787 → Linux systemd-service server 0.0.46-nightly.20261007.2761, Tailscale direct route.

    — Claude Code (claude-opus-5-5) via t3 triage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs more infoInitial triage showed no bug. Awaiting more infovia-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions