Skip to content

Revoking a linked environment's token under Authorized clients breaks the link silently, and the other machine still shows it as reachable #26772

Open

Description

@EtanHey

What happened

Two Macs were linked to each other with Linked environments (M1 → M4 and M4 → M1). A few hours later, agents on the M1 started getting this error from every call to the M4 (t3_thread_send, reads, delegation):

The linked environment no longer accepts this link. It may have been revoked there; link it again.

The user didn't knowingly revoke anything and asked, "Why was it revoked? It worked perfectly earlier." Settings → Connections on the M1 kept showing the M4 link as reachable, which made it more confusing.

Diagnosis

  1. The M4's /mcp answered the M1's bearer token with HTTP 401. That maps to the capability_denied message in apps/server/src/peer/PeerMcpClient.ts (lines 142 and 190).
  2. On the M4, the session behind the M1's link (auth_sessions, subject mcp-client, method bearer-access-token, label T3 Code · <M1 label>, issued at the link time and expiring 30 days later to the second, the same as the M1's expiresAt) had revoked_at set. Only that one row was revoked at that moment, so it was a single revoke, not "revoke other clients". It happened through POST /api/auth/clients/revoke. No agent tool call on the M4 in that window touched auth. A minute later the user was asking whether to revoke the MCP authorized clients set up that morning, so the most likely path is a Revoke click under Settings → Connections → Authorized clients.
  3. UI gap: ConnectedClientListRow (apps/web/src/components/settings/AuthorizedClientsSettings.tsx) renders a linked environment's token as a plain row: the client label plus a one-click destructive Revoke. There's no "Linked environment" badge, no confirmation, and no warning that revoking it breaks that machine's link. The server already knows the difference (McpClientSession.peerLink, EnvironmentAuth.ts authenticateMcpClient), but the list doesn't show it. Next to hand-made MCP clients, it looks like one of them.
  4. Misleading status: in PeerLinks.ts, statusOf probes only the unauthenticated environment descriptor. A link whose token has been revoked therefore keeps reporting status: "reachable", with the 401 shown only in lastError. Settings shows the machine as reachable while every authenticated call fails.

Steps to reproduce

  1. Link machine A to machine B (Settings → Connections → Linked environments).
  2. On B, open Settings → Connections → Authorized clients. The link's token shows as T3 Code · <A's label> and looks the same as any other MCP client.
  3. Click Revoke on that row. There's no confirmation.
  4. On A, call any linked-environment tool against B (for example t3_thread_send with B's environmentId). It fails with capability_denied: "no longer accepts this link".
  5. On A, call t3_environment_links or open Settings → Connections. B is still reachable.

Version

0.1.4-nightly.20261028.3841 on both machines when triaged. The revoke happened the evening before, and the M4 may still have been on the previous nightly at that point.

Environment

macOS 26 (Darwin 25.5.0), arm64, on both Macs (M1 Pro and M4 Max). The machines are linked over Tailscale. Node v24.22.0.

Evidence

# A (M1): t3_environment_links
{"environmentId":"<B>","label":"MacBook Pro","status":"reachable","access":"full-access",
 "expiresAt":"2026-11-27T11:36:08.836Z",
 "lastError":"The linked environment no longer accepts this link. It may have been revoked there; link it again."}

# B (M4): auth_sessions, read-only
subject=mcp-client method=bearer-access-token client_label="T3 Code · Local’s MacBook Pro"
issued_at=2026-10-28T11:36:08.879Z expires_at=2026-11-27T11:36:08.879Z revoked_at=2026-10-28T21:53:01.304Z
# no other session revoked in that second; no mcp-client session issued around it

Related issues

Suggested direction

  • Mark linked-environment tokens in Authorized clients (for example a "Linked environment: " badge), and confirm before revoking one ("This breaks 's link to this environment").
  • After an authenticated call returns 401, have the linking side show the link as revoked / needs relinking instead of reachable.

Fix applied or workaround

Workaround: re-link A → B from A (a relink was started during triage). Nothing else was changed on either server.

Filed by

Claude Code (claude-opus-5-5), triage session started from T3 Code Desktop

Activity

  1. Kamkmgamer commented on Oct 29, 2026

    @Kamkmgamer
    Contributor

    I’m taking this issue. I’ll trace the linked-environment token revoke and 401 handling, then push a focused fix with tests.

  2. EtanHey commented on Oct 29, 2026

    @EtanHey
    ContributorAuthor

    Two more problems came up while relinking (same machines, 0.1.4-nightly.20261028.3841):

    1. The link card's "Use this link" accepts a revoked link and reports success.
    After the revoke above, an agent called t3_environment_link for B. The card offered Use this link for the existing, revoked-but-unexpired link, and answering it gave linkStatus: "linked". No new token was issued: B's auth_sessions showed nothing new, and the next call still got a 401. answerOutcome → use-existing → usableLink (apps/server/src/peer/PeerLinkRequests.ts) only checks the local row and its expiry, never whether the token still works.

    2. After an agent unlinks, the desktop's link list goes stale and the card keeps offering "Use this link".
    After t3_environment_unlink (server side: peer_environment_links empty, t3_environment_links returns []), the link card and the Settings link dialog on the desktop app still marked B as linked. linkableMachines takes linked from the cached peerLinkEnvironment.list query, and nothing refreshes it. Every answer took the use-existing path and failed with "That environment is no longer linked here, or its link expired. Link it again." This happened twice in a row. Reloading the window (Cmd+R) cleared it, and the next card went through the real two-step pairing and linked properly.

    Working recovery today: unlink on A, reload the A desktop window, then link again.

    Filed by Claude Code (claude-opus-5-5) via t3 triage.

  3. Kamkmgamer commented on Oct 30, 2026

    @Kamkmgamer
    Contributor

    I have a tested fix ready for this report: identify linked sessions before revocation, require confirmation, show authenticated 401s as revoked, and require a working credential before reusing a link. It also refreshes client link lists after agent unlinking.

    Before I open a PR, could a maintainer triage the failure and confirm this intended behavior, as required by the contribution guide? The implementation branch is https://github.com/Kamkmgamer/t3code/tree/t3/fix-linked-environment-token-revoke. Focused tests, a live model eval, and real-client before/after, bulk-revoke, and relink evidence are ready.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions