Repository navigation
[Bug]: Remote environments stay switched off after a protocol mismatch, even once the host is updated #15051
Description
Activity
Note
Grok responding on behalf of Julius.
Triage
Thanks for the write-up, @vitalyiegorov. This is a real bug, and it's separate from #14979.
What's wrong:
EnvironmentRegistry.setCompatibilityrecords a protocol rejection as if the user had switched the environment off. When a saved environment is on, it setsenabled: falseand callsregistrations.setEnabled(id, false), which writes to the persisted switched-off list.unsupportedReasonlives only in memory. When a later compatible health check callssetCompatibility(id, null), only the reason is cleared:enabledstays false and nothing reconnects. After a relaunch the reason is gone, so the row shows Off with the Switched off tooltip. That's the same thing @michft described on #14979 once both hosts were on the same nightly.The merged #11990 added this to stop an incompatible server from sitting in a retry loop. Holding the connection off while the host is old makes sense, but it shouldn't become the saved state once the host is compatible again. The in-app update flow already recovers, because
outdatedHostUpdateclears the block and then callssetEnabled(true). A host updated on its own (launchd, systemd, or a manual upgrade) never goes through that path, so its threads stay hidden until someone notices the switch.Intended behavior: compatibility should be runtime state, not a saved setting.
- While the protocol doesn't match, keep
unsupportedReason, disconnect, and show Client not supported with the switch disabled. That should apply to both relay discovery and a socket preflight rejection. - Leave
enabledand the persisted switched-off list untouched for that block, so an environment the user turned off stays off. - When a fresh check clears the block, reconnect if
enabledis still true. Discovery should still ignore a replayed health result, so an older relay snapshot can't clear a newer socket rejection. - Only reconnect when the block is cleared, so a host that's still on an old build doesn't loop.
Fix scope: the
packages/client-runtimeregistry, plus the registry tests that currently expect the opposite. One trap:setEnabled(true)returns early whenenabledis already true. Once the block stops flippingenabled,setCompatibility(null)has to connect an enabled environment itself, or the in-app update flow stops resuming.Rows that were already saved as switched off will stay off. They have no stored reason, so they can't be told apart from a real user toggle, and on those machines the workaround is still to switch each environment back on once.
#14979 covers the dark-mode switch contrast, which the open PR #14984 addresses. This issue covers environments that stay off after the host becomes compatible again. A maintainer will decide on the fix direction.
- While the protocol doesn't match, keep
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
on Oct 3, 2026 - added 3 commits that reference this issue
on Oct 3, 2026
Before submitting
Area
Not sure
Steps to reproduce
0.0.46-nightly.20261003.2610). A saved T3 Connect host, switched on, is still on the old protocol. Its row shows Client not supported.Expected behavior
The environment reconnects once its host is compatible. The user never switched it off.
Actual behavior
It stays Off (tooltip: Switched off), and its threads disappear until the user notices and turns it back on by hand.
Cause
setCompatibilityinpackages/client-runtime/src/connection/registry.tswrites an incompatible environment into the user's persisted switched-off list (registrations.setEnabled(id, false)). The reason (unsupportedReason) is kept only in memory. When a fresh check clears it, or after a relaunch, the entry is indistinguishable from one the user switched off, so nothing turns it back on.Suggested fix
Treat compatibility as runtime state. Keep setting
unsupportedReasonand disconnecting, but stop changingenabledor the persisted list. Connect only whenenabled && !unsupportedReason, and reconnect when the block clears. An environment the user switched off stays off. I can open the PR.Impact
Major degradation or frequent failure
Version or commit
t3@0.0.46-nightly.20261003.2610 (main 8283b48)
Environment
macOS desktop client. Hosts: macOS (launchd) and Linux (systemd) services over T3 Connect.
Screenshots, recordings, or supporting files
Both hosts updated to the same nightly with relay tunnels registered. The client still shows them switched off:
Workaround
Turn each environment back on in Settings → Connections.
Related