Skip to content

[Bug]: A connection switched off as unsupported stays blocked after the host is updated to V2 directly #15410

Description

@dev-ankit

Area

packages/client-runtime (connections), surfaced in apps/web Settings → Connections

Summary

If a v2 client disables a saved direct connection because the host was still on v1, the connection stays disabled after the host is updated to v2 some other way. The switch is disabled ("Client not supported"). The only action left is Update, which fails against a host that is already on v2.

Steps to reproduce

  1. Save a direct (non-relay) connection from a Nightly desktop client to a remote host, here a Windows desktop reached over a Tailscale IP.
  2. Update the client to a v2 Nightly while the host is still on v1. The client marks the environment unsupported (serverUpdateRequired) and switches it off.
  3. Update the host to the same v2 Nightly yourself on that machine, not through the client's Update button.
  4. On the client, open Settings → Connections.

Expected behavior

The client sees that the host now speaks orchestration protocol 2, clears the block and lets the connection be switched back on. Pressing Update when the host is already compatible should do the same.

Actual behavior

  • The switch stays disabled, and nothing clears the block. unsupportedReason is only cleared by relay discovery (connection/layer.ts, relay targets only) or by a successful updateOutdatedHost. A disabled direct connection never runs a socket handshake, so it never checks again.
  • Pressing Update calls updateOutdatedHost. That gets its socket URL from resolver.prepareForUpdate (= authorize), which does not call appendOrchestrationProtocol, and it never checks whether the descriptor it just fetched is already compatible. The v2 host rejects the bare socket with 426 orchestration_protocol_incompatible, so the update fails.
  • The UI shows Client not supported and SocketOpenError: An error occurred during Open during update

Impact

Blocks work completely for that connection until the client restarts. It will likely affect anyone who updates their machines one at a time during the move to V2 (#14871).

Version or commit

Nightly 0.0.46-nightly.20261003.2638 (5e35272) on both sides. packages/client-runtime/src/connection/ has not changed on main since then.

Environment

Client: macOS desktop Nightly. Host: Windows 11 desktop Nightly (NT 10.0.26200, x64), direct connection over Tailscale.

Logs

Host server.trace.ndjson, requests from the macOS client (user agent T3Code(Nightly)/0.0.46-nightly.20261003.2638). The descriptor and ticket requests succeed, then the socket is rejected:

http.server GET  /.well-known/t3/environment   status=200
http.server POST /api/auth/websocket-ticket    status=200
http.server GET  /ws                           status=426

apps/server/src/ws.ts returns 426 only when the orchestrationProtocol query param is missing or wrong.

Possible fix

In updateOutdatedHost, if the descriptor from prepareForUpdate already passes isCompatibleDescriptor, skip the self-update RPCs and go straight to the resume step: clear compatibility and re-enable.

Workaround

Confirmed: restart the client, then switch the connection back on in Settings → Connections. This works because unsupportedReason is held in memory and only enabled: false is persisted.


Investigated with Claude Code (Claude Opus 5.5).

Activity

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