Skip to content

[Bug]: Saved T3 Connect environments keep their original label after the host's machine name changes #15683

Open

Description

@jlipworth

Before submitting

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

Area

apps/web

(The bug is in packages/client-runtime, which all clients share — web, desktop and mobile — plus infra/relay.)

Steps to reproduce

  1. Link a Mac whose ComputerName is JL-Mac-Studio-M3-Ultra to T3 Connect, then add it as an environment on a client.
  2. Move to a new Mac with Migration Assistant. It copies ~/.t3/userdata/environment-id, so the environmentId stays the same. The new machine is named JL-Mac-Studio-M5-Ultra.
  3. Start T3 Code on the new Mac. In the client from step 1, open Settings → Connections → Environments and check the environment chip in the composer.

Expected behavior

The environment is shown as JL-Mac-Studio-M5-Ultra. That is the name the server reports in its descriptor, and the name a fresh T3 Connect discovery list shows.

Actual behavior

Settings → Environments and the composer environment chip still show JL-Mac-Studio-M3-Ultra, next to "T3 Connect · Connected". A T3 Connect environment that has not been saved on the client yet shows the new name.

The host itself is fine. scutil --get ComputerName, scutil --get LocalHostName, scutil --get HostName and hostname all return JL-Mac-Studio-M5-Ultra. The server reads its label from scutil --get ComputerName every time it starts (apps/server/src/environment/ServerEnvironmentLabel.ts).

Impact

Cosmetic issue

Version or commit

Desktop 0.0.46-nightly.20261004.2648; main @ 4ee6bfd

Environment

macOS 27.0.1, Apple M5 Ultra, T3 Code (Nightly) desktop, T3 Connect

Logs or stack traces

No response

Screenshots, recordings, or supporting files

Composer chip shows JL-Mac-Studio-M3-Ultra

Settings environments row shows JL-Mac-Studio-M3-Ultra

Workaround

From reading the code (not tested): remove the saved environment and add it again from T3 Connect. The label is copied from discovery again when the environment is added.


Root cause

Two copies of the label are stored, and neither one is ever updated:

  1. The client's saved target keeps the label it had when it was added. When an environment is added, RelayConnectionTarget.label is copied from the discovery record. This happens in apps/web/src/components/cloud/CloudEnvironmentConnectList.tsx, apps/mobile/src/features/connection/useConnectionController.ts, and the legacy migration in apps/desktop/src/app/DesktopConnectionCatalogStore.ts. Settings and the composer chip display that catalog entry. On every connect, ConnectionResolver.authorize in packages/client-runtime/src/connection/resolver.ts fetches the live ExecutionEnvironmentDescriptor, but it only compares environmentId and discards descriptor.label. Discovery results are never written back into saved targets either. Bearer and SSH saved environments store label the same way, so they probably have the same problem.
  2. The relay link row is only updated on an explicit re-link. relay_environment_links.environment_label is written only by EnvironmentLinks.upsert in infra/relay/src/environments/EnvironmentLinks.ts. That runs when the environment is linked through desktop T3 Connect linking or t3 connect. A server boot does not refresh it, so discovery also shows the old name if the host is renamed without re-linking.

Suggested fix

  • Smallest fix: once authorize succeeds, compare descriptor.label with target.label. If they differ, write the new label to the catalog entry. The descriptor is already fetched on every connect, so this adds no request, and it fixes relay, bearer and SSH environments together.
  • Optional: when relay discovery refreshes, sync the labels of saved relay targets so that offline environments also get the new name.
  • Relay: refresh environment_label when the server re-establishes its managed endpoint.
  • If Manage T3 Connect environment names and registrations #13057 adds custom names that apply across the account, the rule should be "follow the advertised machine name unless the user renamed it". That keeps it to one label instead of adding a second label field.

Related

Activity

  1. jlipworth commented on Oct 4, 2026

    @jlipworth
    Author

    Screenshots, taken on the client after the host was renamed to JL-Mac-Studio-M5-Ultra:

    Composer environment chip: still shows the old name

    Composer chip shows JL-Mac-Studio-M3-Ultra

    Settings → Environments: old name, connected through T3 Connect

    Settings environments row shows JL-Mac-Studio-M3-Ultra, T3 Connect · Connected

  2. juliusmarminge commented on Oct 4, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the thorough report, @jlipworth. The Migration Assistant detail and the root-cause notes lined up well with the code.

    What I found

    Confirmed on main at 4ee6bfd50e. This is separate from #13057.

    • The saved label never updates. Settings → Environments and the composer chip show the saved catalog label (entry.target.label). That label is copied once, when the environment is added: in CloudEnvironmentConnectList, in the mobile connect path, and in the desktop catalog migration.
    • The live name is fetched but dropped. ConnectionResolver.authorize loads the live ExecutionEnvironmentDescriptor on every connect and checks environmentId, then discards descriptor.label. Relay auth and discovery health also read the descriptor, but neither writes the name back to the saved target.
    • Why remove and re-add works. EnvironmentRegistry.register replaces target.label, which matches the workaround you suggested.
    • When the server advertises a new name. resolveServerEnvironmentLabel runs scutil --get ComputerName once per process, so a restart is what picks up the new name.
    • The relay row is a narrower gap than described. environment_label is written only by EnvironmentLinks.upsert. Startup calls that only when managedTunnelStartupAction returns reconcile_link, so an already-linked host that comes back ready keeps its old relay label. Your unsaved T3 Connect row showing the new name suggests the link was refreshed during the migration, which points to the saved catalog as the stale copy here.
    • Other environment types. Bearer and SSH targets store label the same way, so they're probably affected too. The local primary and desktop-local backends already rebuild from the descriptor.

    Likely fix area

    • One option: after a successful authorize, update the catalog entry's label whenever descriptor.label differs. That needs no extra request and covers relay, bearer, and SSH targets alike.
    • Optionally, sync saved relay targets from discovery, and refresh environment_label for already-linked hosts on startup.
    • How this should work alongside the custom names requested in Manage T3 Connect environment names and registrations #13057 is still open.

    A maintainer will decide on the fix direction.

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

    @timharris707

    Claude Opus 5.5 via Claude Code, responding on behalf of Tim Harris:

    Adding a data point from #21270, which was closed as a duplicate of this issue. On 0.1.0, running t3 connect link again, and even t3 connect unlink followed by t3 connect link, did not refresh the relay's environment_label. The old name kept showing in a fresh discovery list and under T3 Account > T3 Connect > Registered servers, not only in saved entries.

    So a fix that only updates the client's saved label after authorize would not cover this case. The relay seems to keep the label from the first link for as long as the environment identity exists.

    #21270 also describes a separate problem this issue doesn't cover: after creating a new environment identity, every client got environment_link_not_found until a full t3 connect logout and sign-in. Happy to file that on its own if it's useful.

  5. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Checked current main at b5a226e49c in an isolated Linux worktree. Ran vp run dev, opened the web client, then Settings → Connections → Add environment. This development build offers only host/code pairing, with no T3 Connect discovery, so I could not run the saved-relay rename sequence. The real-data snapshot also failed migration, so this attempt used empty state. This is not a successful reproduction or evidence that the bug is fixed.

    Can you confirm on the latest nightly whether restarting the renamed host leaves (1) its saved environment label and (2) its fresh T3 Connect discovery label stale? Include the client and host versions. The later comment reports both labels staying stale, whereas the original report says fresh discovery has the new name.

  6. YasserDRIF commented on Oct 26, 2026

    @YasserDRIF

    Another repro on the current release, for the "saved label stale after host restart" case.

    Host: macOS (arm64), T3 Code server 0.1.2

    Steps

    1. Renamed the Mac from Yasser's MacBook Pro (2) to Yasser - Suture (scutil --set for ComputerName, LocalHostName, and HostName).
    2. Quit T3 Code desktop fully and reopened it.
    3. Force-closed the iOS app and reopened it. It's connected to this host through T3 Connect.

    Result

    • The host now advertises the new name. The environment descriptor returns label: "Yasser - Suture" with the same environmentId as before.
    • The desktop app shows the new name.
    • The mobile app still shows Yasser's MacBook Pro (2) for this environment after a full restart of both the host and the app.

    So (1) the saved environment label on the mobile client stays stale even though the restarted host advertises the new name. I haven't checked (2), the fresh discovery list, yet. I'll add the mobile app version and the discovery result when I have them.

  7. Hormold commented on Nov 6, 2026

    @Hormold

    +1, hit this today on 0.1.8 nightly. got 2 macs paired and they show up as "MacBook Pro" and "MacBook Pro 4" lol. renamed the second one in macos, its server already returns "Old Mac" from /.well-known/t3/environment but the desktop app still shows MacBook Pro 4

    only way i found to fix it is remove from this device -> new pairing code -> pair again. thats too much for a name change

    can you just add Rename to the ... menu in Settings > Connections? local name only, nothing on the server. and if i didnt set a custom name just take the label from the server on reconnect, that would fix this issue too

  8. jacobcorbett commented on Nov 6, 2026

    @jacobcorbett
    Contributor

    Additional reproduction on stable 0.1.7 (6 November 2026): native Windows 11 host, macOS desktop client, T3 Connect.

    After renaming the Windows machine, the same environment identity advertised its new name through /.well-known/t3/environment. Both the saved client environment row and the fresh T3 Connect discovery row continued to show the old name. The peer-linked environments section already showed the new name.

    What we checked:

    • Restarting the macOS client did not update the name.
    • Removing the saved environment from the Mac left an unsaved discovery row with the old name, so this was also the relay account record, not only the saved target.
    • Restarting the Windows T3 scheduled task did not update discovery.
    • t3 connect unlink, t3 connect link --headless, and restarting the host caused startup link reconciliation. The macOS discovery/saved row then showed the new name.

    The unlink operation initially reported upstream_unavailable; subsequent startup reconciliation succeeded. The descriptor retained the same environment ID. We did not create a new identity.

    The relink also caused a separate client-side outage matching #27250: the tunnel was connected, but the client's recursive DNS chain cached NXDOMAIN for its hostname while a public resolver returned valid records. HTTPS to the exact environment descriptor endpoint succeeded when resolved to the public address. A domain-specific DNS resolver override restored normal client connectivity. This reinforces the value of refreshing the advertised name without unlinking/relinking.

    PR #27542 addresses saved client labels; this reproduction also needs the relay discovery label refreshed for an already-linked host. No claim of reproduction on the latest nightly or current main.

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