Skip to content

[Bug]: Stable t3 pair prints an unusable token for a running Nightly/V2 server #15492

Description

@walterbarrera1234

Before submitting

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

Area

apps/server

Steps to reproduce

  1. Run T3 Desktop Nightly 0.0.46-nightly.20261004.2644 on macOS with its existing T3 home after V2 migration. The live environment descriptor reports orchestrationProtocolVersion: 2.
  2. On the same Mac, run npx t3 pair. In the observed setup this selected stable CLI 0.0.45. To keep the CLI version deterministic, use npx --yes t3@0.0.45 pair.
  3. Use the freshly generated pairing URL with the live server before the token expires. The command prints a QR, URL, token, and expiry as if pairing can succeed.
  4. The receiving client reports an invalid pairing token.

Expected behavior

The CLI should generate a credential usable by the discovered running server, or reject an incompatible server/CLI pairing before opening or writing a database. A channel/protocol mismatch should give an actionable explanation and a command using the matching server version.

Actual behavior

The stable CLI discovered the running Nightly server but issued its link in V1 state.sqlite. The running Nightly server used V2 statev2.sqlite and could not see that credential. The command appeared successful; the later invalid-token message did not identify the version/database mismatch.

Read-only database metadata checks located the stable command's new link in state.sqlite and showed no corresponding new link in statev2.sqlite. Issuing a replacement with the matching Nightly CLI created a link in statev2.sqlite and pairing succeeded. The existing HTTPS discovery endpoint continued to reach the intended protocol-2 server.

Impact

Major degradation: the default npx pairing command appears to work but cannot pair to an already-running V2 host. A matching-version command provides a workaround.

Version or commit

Pairing CLI: t3 0.0.45 (stable).
Running Mac desktop/server: 0.0.46-nightly.20261004.2644, orchestration protocol 2.
Working replacement CLI: 0.0.46-nightly.20261004.2644.
Observed October 4, 2026.

Environment

macOS T3 Desktop, existing user T3 home containing both V1 and V2 databases, CLI invoked via npx. Tailscale provided private HTTPS access. The owner confirmed successful Safari pairing and then native iPhone pairing after the workaround. No separate development worktree server was involved in this diagnosis. Exact macOS, Node, and iPhone build numbers were not captured.

Logs or stack traces

No stack trace was captured. Pairing URLs, credentials, hostnames, account identities, and network addresses are omitted.
Nonsecret metadata from the original stable link:

  • state.sqlite: created_at 2026-10-04T04:49:08.849Z; expires_at 2026-10-04T04:54:08.849Z.
  • statev2.sqlite: no corresponding new link at that time.
    Replacement generated by the matching Nightly CLI:
  • statev2.sqlite: created_at 2026-10-04T04:54:00.561Z; expires_at 2026-10-04T05:09:00.561Z.

Workaround

Run on the machine hosting the already-running server:

npx --yes t3@0.0.46-nightly.20261004.2644 pair --tailscale --ttl 15m

Use the exact running server version for later setups. npx --yes t3@nightly pair --tailscale also worked when the nightly tag matched the installed server. Use a fresh token per receiving app/browser; opening it in Safari authorizes Safari separately from the native phone app.

Related context

#10516 is related to the pairing CLI opening an installed server's database using another runtime's schema, but concerns development-worktree migrations rather than stable/V2 tokens being written to different databases.
#10516

V2 migration documents separate state.sqlite / statev2.sqlite databases:
#14871

The observed Nightly pairing implementation discovers the running server and derives storage paths before issuing the token:
https://github.com/pingdotgg/t3code/blob/v0.0.46-nightly.20261004.2644/apps/server/src/cli/pair.ts

Activity

  1. juliusmarminge commented on Oct 4, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the really thorough report, @walterbarrera1234, especially the read-only database checks and the working command. This looks like a real pairing bug, and it isn't a duplicate of #10516 or #14871.

    What I found

    • t3 pair finds the running server through userdata/server-runtime.json, which V1 and V2 still share, but then writes the token to the CLI's own database. On v0.0.45 that's state.sqlite, and on v0.0.46-nightly.20261004.2644 it's statev2.sqlite.
    • apps/server/src/cli/pair.ts is the same on both versions and doesn't compare the discovered server's orchestrationProtocolVersion (1 vs 2) or serverVersion with its own before writing. So the stable CLI can print a valid-looking QR and URL for the Nightly server while the credential only exists in the V1 database.
    • The Nightly server then rejects it with the generic "Invalid pairing token" message, which doesn't hint at the version or database mismatch.
    • [Bug]: Worktree pairing can migrate the live desktop database #10516 is a different failure (a worktree checkout migrating the live install). [IMPORTANT] Moving from T3 Code Orchestrator V1 to V2 #14871 notes that V1 and V2 clients refuse a mismatched connection, whereas this command reports success instead.

    Your matching-version workaround (npx --yes t3@<running server version> pair) is the right one for now.

    Likely fix area

    • t3 pair in apps/server/src/cli/pair.ts: one option is to check the discovered descriptor's protocol and server version before opening a database, and exit with the exact matching npx t3@<server version> pair command when they differ.
    • Since the published t3@0.0.45 would keep behaving this way, there's also a question of whether the stable package needs a patch so npx t3 pair fails clearly while a Nightly V2 server is running.
    • Possibly a clearer server-side message when a pairing token isn't found.

    A maintainer will decide on the fix direction.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 4, 2026
  3. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Fresh triage: this reports a pairing compatibility bug, not an exploitable vulnerability. No duplicate found in open issues from the last 90 days for stable/Nightly pairing, V1/V2 token storage, or “invalid pairing token”.

    At 07d38b8d17, code inspection shows pairCommand discovers the running server, derives local database paths, then calls EnvironmentAuth.createPairingLink. Addressing the reported mismatch touches pairing authentication/credential handling, so the automated triage hard stop requires maintainer handling. No runtime reproduction or code changes were made; leaving this open for Julius.

  4. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Reproduced on Linux with current main at 044f07257c: t3@0.0.45 pair printed a token for a protocol-2 server, which rejected the fresh credential with HTTP 401. The matching CLI succeeded. #23789 adds a protocol check before database access, with a matching-version command on rejection. The already-published 0.0.45 package remains affected.

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

    bugSomething is broken or behaving incorrectly.via-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