pingdotgg / pingdotgg/t3code

[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)

Open
#11,899 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accepted bug via-triage
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_only mode (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

  1. Get into the drifted state described in #11898 (relay record manual, local cloud-endpoint-runtime-config present). The quickest way without simulating a write failure: link in managed mode, then with a copy of cloud-endpoint-runtime-config.bin saved 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.
  2. Open Settings > Connections. The T3 Connect toggle shows on.
  3. Toggle it off and on. Observe the toast "T3 Connect tunnel disabled" then "T3 Connect linked", and the relay record is still manual if publishing was on for the "off" step. (If publishing was off, this sequence does work, which is the workaround.)
  4. 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. refreshRelayEnvironments already fetches the environment list including endpoint.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_managed on 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.