[Bug]: Connections settings cannot detect or repair a relay link that drifted to publish-only (toggle shows on, relink is a no-op, mobile gets endpoint_provider_not_managed)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
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
Steps to reproduce
Companion to #11898 (non-atomic relay-config apply) and to #6568. That issue is about how relay and desktop get out of sync. This one is about the desktop not being able to see it or fix it once it has happened.
Why the UI cannot recover
useCloudLinkController (apps/web/src/cloud/useCloudLinkController.ts) decides whether to relink like this:
if (!linked || managedTunnelActive !== desired.managedTunnel) {
await linkPrimaryEnvironment({ ..., mode: desired.managedTunnel ? "managed" : "publish_only" });
}
managedTunnelActive comes from readCloudLinkState on the local environment server, which is just Option.isSome(secrets.get(CLOUD_ENDPOINT_RUNTIME_CONFIG)). It never consults what the relay actually holds for this environment (endpoint.providerKind on the /v1/client/environments record). So when the relay says manual and the local secret says managed, the toggle already renders as "on" and switching it on again is a no-op. The user has no action that rewrites the relay record short of knowing to unlink completely first.
Two smaller things in the same area make this harder to get out of:
- With Publish agent activity on, turning T3 Connect off does not unlink. It relinks in
publish_onlymode (ConnectionsSettings.tsx,updateManagedTunnel, toast text "The managed tunnel was removed. Agent activity publishing stays on."). That is documented in the code comments, so it is intentional, but the UI does not say that the only way to get a fresh managed link is to turn publishing off first. - On the mobile side the error is
Relay rejected the environment connection request (endpoint_provider_not_managed), which gives the user nothing to act on. The relay's own reason text is "the linked endpoint is not relay-managed" (EnvironmentConnector.ts,describeReason), which is closer, but neither says "the desktop linked this environment in publish-only mode, turn T3 Connect on there".
Repro
- Get into the drifted state described in #11898 (relay record
manual, localcloud-endpoint-runtime-configpresent). The quickest way without simulating a write failure: link in managed mode, then with a copy ofcloud-endpoint-runtime-config.binsaved aside, turn T3 Connect off while publishing is on, then restore the saved file and restart T3 Code. Local now says managed, relay says manual. - Open Settings > Connections. The T3 Connect toggle shows on.
- Toggle it off and on. Observe the toast "T3 Connect tunnel disabled" then "T3 Connect linked", and the relay record is still
manualif publishing was on for the "off" step. (If publishing was off, this sequence does work, which is the workaround.) - Connect from the mobile app.
endpoint_provider_not_managed.
Expected behavior
managedTunnelActive(or a sibling field) should reflect the relay's view of the link, not only the presence of a local secret.refreshRelayEnvironmentsalready fetches the environment list includingendpoint.providerKind; comparing that against the local runtime config and surfacing "T3 Connect is out of sync, re-link" would be enough.- A "Re-link" or "Repair" action in Settings > Connections that always runs a fresh managed link regardless of what the toggle currently shows.
- When the user turns T3 Connect off while publishing is on, tell them it becomes publish-only and that a full unlink needs publishing off as well.
- Map
endpoint_provider_not_managedon mobile (and in the desktop connections list) to text that says what to do on the desktop.
Actual behavior
The toggle shows on, toggling does nothing to the relay record, and the environment stays discoverable but unconnectable from mobile until the user discovers the publish-off, tunnel-off, tunnel-on sequence. #6568 and its comment show two other users hitting the same wall, one of them after an environment_link_not_found and a tunnel logout/login, so this is not only reachable via the write-failure path.
Impact
Major degradation or frequent failure
Version or commit
Desktop 0.0.40 (release channel). Code references are against main as of 2026-09-15.
Environment
Windows 11 Home 10.0.26200, T3 Code desktop 0.0.40, iOS T3 Code app.
Logs or stack traces
Connection failed. Reason: Relay rejected the environment connection request (endpoint_provider_not_managed). trace id: ad7746aff889c11de16074675a73acda
Workaround
Settings > Connections: turn Publish agent activity off, turn T3 Connect off, turn T3 Connect on, turn publishing back on. Verified working on 2026-09-15: all six cloud-* secrets were rewritten together, cloudflared restarted, and the mobile app connected on the next attempt.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with apps/web/src/cloud/useCloudLinkController.ts and refreshRelayEnvironments, then inspect ConnectionsSettings.tsx and EnvironmentConnector.ts for the existing link state and reason handling. Reproduce the drifted relay/manual versus local-managed state using the documented steps. Done means the UI can identify and repair the mismatch, explains publish-only behavior, and gives actionable text for endpoint_provider_not_managed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, cloud, full-stack
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100