Repository navigation
Description
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
- The M4's
/mcpanswered the M1's bearer token with HTTP 401. That maps to thecapability_deniedmessage inapps/server/src/peer/PeerMcpClient.ts(lines 142 and 190). - On the M4, the session behind the M1's link (
auth_sessions, subjectmcp-client, methodbearer-access-token, labelT3 Code · <M1 label>, issued at the link time and expiring 30 days later to the second, the same as the M1'sexpiresAt) hadrevoked_atset. Only that one row was revoked at that moment, so it was a single revoke, not "revoke other clients". It happened throughPOST /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. - 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.tsauthenticateMcpClient), but the list doesn't show it. Next to hand-made MCP clients, it looks like one of them. - Misleading status: in
PeerLinks.ts,statusOfprobes only the unauthenticated environment descriptor. A link whose token has been revoked therefore keeps reportingstatus: "reachable", with the 401 shown only inlastError. Settings shows the machine as reachable while every authenticated call fails.
Steps to reproduce
- Link machine A to machine B (Settings → Connections → Linked environments).
- 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. - Click Revoke on that row. There's no confirmation.
- On A, call any linked-environment tool against B (for example
t3_thread_sendwith B'senvironmentId). It fails withcapability_denied: "no longer accepts this link". - On A, call
t3_environment_linksor open Settings → Connections. B is stillreachable.
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 itRelated issues
- [Bug]: WSL backend goes offline after restart: duplicate desktop-bootstrap exchange revokes the cached session #22951 (desktop-bootstrap exchange revokes a cached session) and SwiftUI app keeps retrying a revoked direct pairing instead of asking to pair again when the host has several routes #17591 (SwiftUI app keeps retrying a revoked pairing) both involve revoked sessions, but neither covers linked-environment tokens in the Authorized clients list or the reachable-after-revoke status.
- Linked environments selects a Tailscale IP that its security check rejects #26450 is a different Linked environments failure (a Tailscale IP gets rejected).
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 ofreachable.
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
Kamkmgamer commentedon Oct 29, 2026
I’m taking this issue. I’ll trace the linked-environment token revoke and 401 handling, then push a focused fix with tests.
EtanHey commentedon Oct 29, 2026
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_linkfor B. The card offered Use this link for the existing, revoked-but-unexpired link, and answering it gavelinkStatus: "linked". No new token was issued: B'sauth_sessionsshowed 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_linksempty,t3_environment_linksreturns[]), the link card and the Settings link dialog on the desktop app still marked B as linked.linkableMachinestakeslinkedfrom the cachedpeerLinkEnvironment.listquery, and nothing refreshes it. Every answer took theuse-existingpath 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.
Kamkmgamer commentedon Oct 30, 2026
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.