Before submitting
Area
packages/contracts or packages/shared
Steps to reproduce
- On macOS arm64, have an old Homebrew
cloudflared on PATH. Mine was 2023.8.2, installed in 2023 and never upgraded.
- Make sure T3's managed copy isn't installed yet (
~/.t3/tools/cloudflared/2026.5.2/darwin-arm64/cloudflared absent).
- Enable T3 Connect on that Mac from the desktop app.
- Open the environment from the iOS app.
Expected behavior
T3 runs a cloudflared that supports the flags it passes, either its pinned managed copy or a PATH binary it has checked. If the tunnel can't stay up, the host and the phone say so.
Actual behavior
The phone shows Failed to connect. Reconnecting... Reason: Relay could not reach the environment endpoint (endpoint_request_failed) forever. My other Mac, on the same account, connects fine.
The relay error hides the real problem. RelayClient.resolve checks the override env var, then the managed path, then any cloudflared on PATH. It doesn't check the PATH binary's version, and it reports version: CLOUDFLARED_VERSION for it anyway:
|
const resolve: RelayClientShape["resolve"] = Effect.gen(function* () { |
|
const config = yield* loadCloudflaredConfig; |
|
if (Option.isSome(config.executableOverride)) { |
|
return (yield* isExecutableFile(config.executableOverride.value)) |
|
? { |
|
status: "available", |
|
executablePath: config.executableOverride.value, |
|
source: "override", |
|
version: CLOUDFLARED_VERSION, |
|
} |
|
: { status: "missing", version: CLOUDFLARED_VERSION }; |
|
} |
|
if (yield* isExecutableFile(managedPath)) { |
|
return { |
|
status: "available", |
|
executablePath: managedPath, |
|
source: "managed", |
|
version: CLOUDFLARED_VERSION, |
|
}; |
|
} |
|
const pathExecutable = yield* resolvePathExecutable; |
|
if (pathExecutable) { |
|
return { |
|
status: "available", |
|
executablePath: pathExecutable, |
|
source: "path", |
|
version: CLOUDFLARED_VERSION, |
|
}; |
|
} |
|
return releaseAsset |
|
? { status: "missing", version: CLOUDFLARED_VERSION } |
|
: { |
|
status: "unsupported", |
|
platform, |
|
arch, |
|
version: CLOUDFLARED_VERSION, |
|
}; |
|
}); |
|
|
Because a PATH binary counts as available, the managed copy never gets installed. The server then spawns it with --output default:
|
["tunnel", "--no-autoupdate", "--loglevel", "info", "--output", "default", "run"], |
cloudflared 2023.8.2 doesn't have that flag, so it exits right away:
$ TUNNEL_TOKEN=x /opt/homebrew/bin/cloudflared tunnel --no-autoupdate --loglevel info --output default run
Incorrect Usage. flag provided but not defined: -output
The supervisor restarts it with backoff (1, 2, 4, 8, 16, 32 s, then every 60 s) and nothing registers. recoverManagedCloudTunnel gets Relay internal error: upstream_unavailable every 2 minutes. None of this reaches the UI. I found it by reading server.trace.ndjson and running the binary by hand.
Impact
Blocks work completely
Version or commit
T3 Code (Nightly) 0.0.43-nightly.20260926.2282; code refs at main @ de251fc
Environment
macOS 27.0 (Darwin 27.0.0) arm64, MacBook Pro. Homebrew cloudflared 2023.8.2 on PATH. T3 Connect iOS app.
Logs or stack traces
# server.trace.ndjson, "Relay client process started; waiting for tunnel connection" (same tunnelId each time)
16:26:03 pid 3103
16:26:03 pid 3538
16:26:04 pid 4264
16:26:06 pid 4910
16:26:10 pid 5205
16:26:18 pid 6151
16:26:34 pid 7166
16:27:06 pid 9145
16:28:06 pid 13702
# environment.cloud.recoverManagedCloudTunnel
16:28:03 Failure EnvironmentHttpInternalServerError: T3 Connect: Relay internal error: upstream_unavailable.
16:30:03 Failure EnvironmentHttpInternalServerError: T3 Connect: Relay internal error: upstream_unavailable.
16:32:03 Success (after installing the managed 2026.5.2 copy, see workaround)
Relay trace ID from the phone: 00dd36630a221ea911bd41bf682473b5.
Workaround
Put T3's pinned binary at the managed path. resolve checks it before PATH, and the server picks it up on its next restart attempt, with no app restart:
DEST=~/.t3/tools/cloudflared/2026.5.2/darwin-arm64
curl -fsSL -o /tmp/cf.tgz https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-darwin-arm64.tgz
shasum -a 256 /tmp/cf.tgz # ba94054c9fd4297645093d59d51442e5e546d07bb0516120e694a13d5b216d38
tar -xzf /tmp/cf.tgz -C /tmp && mkdir -p "$DEST" && install -m 755 /tmp/cloudflared "$DEST/cloudflared"
brew upgrade cloudflared also works. It breaks again whenever T3 bumps CLOUDFLARED_VERSION, though, because the managed path changes and T3 falls back to PATH.
Possible fixes
- Prefer the managed copy. Install it when missing, even if PATH has a
cloudflared, and keep PATH only as a fallback.
- Or run
cloudflared --version on a PATH candidate and skip it below a minimum version. Report the real version, not CLOUDFLARED_VERSION.
- When the relay client crash-loops, show that in the connect status. The phone's
endpoint_request_failed doesn't point to the host.
Related but different causes: #7447 (tunnel counted as running while unreachable), #8844 (same phone error on Windows, maybe the same PATH issue).
Before submitting
Area
packages/contracts or packages/shared
Steps to reproduce
cloudflaredon PATH. Mine was2023.8.2, installed in 2023 and never upgraded.~/.t3/tools/cloudflared/2026.5.2/darwin-arm64/cloudflaredabsent).Expected behavior
T3 runs a
cloudflaredthat supports the flags it passes, either its pinned managed copy or a PATH binary it has checked. If the tunnel can't stay up, the host and the phone say so.Actual behavior
The phone shows
Failed to connect. Reconnecting... Reason: Relay could not reach the environment endpoint (endpoint_request_failed)forever. My other Mac, on the same account, connects fine.The relay error hides the real problem.
RelayClient.resolvechecks the override env var, then the managed path, then anycloudflaredon PATH. It doesn't check the PATH binary's version, and it reportsversion: CLOUDFLARED_VERSIONfor it anyway:t3code/packages/shared/src/relayClient.ts
Lines 224 to 262 in de251fc
Because a PATH binary counts as available, the managed copy never gets installed. The server then spawns it with
--output default:t3code/apps/server/src/cloud/ManagedEndpointRuntime.ts
Line 315 in de251fc
cloudflared 2023.8.2doesn't have that flag, so it exits right away:The supervisor restarts it with backoff (1, 2, 4, 8, 16, 32 s, then every 60 s) and nothing registers.
recoverManagedCloudTunnelgetsRelay internal error: upstream_unavailableevery 2 minutes. None of this reaches the UI. I found it by readingserver.trace.ndjsonand running the binary by hand.Impact
Blocks work completely
Version or commit
T3 Code (Nightly) 0.0.43-nightly.20260926.2282; code refs at main @ de251fc
Environment
macOS 27.0 (Darwin 27.0.0) arm64, MacBook Pro. Homebrew cloudflared 2023.8.2 on PATH. T3 Connect iOS app.
Logs or stack traces
Relay trace ID from the phone:
00dd36630a221ea911bd41bf682473b5.Workaround
Put T3's pinned binary at the managed path.
resolvechecks it before PATH, and the server picks it up on its next restart attempt, with no app restart:brew upgrade cloudflaredalso works. It breaks again whenever T3 bumpsCLOUDFLARED_VERSION, though, because the managed path changes and T3 falls back to PATH.Possible fixes
cloudflared, and keep PATH only as a fallback.cloudflared --versionon a PATH candidate and skip it below a minimum version. Report the real version, notCLOUDFLARED_VERSION.endpoint_request_faileddoesn't point to the host.Related but different causes: #7447 (tunnel counted as running while unreachable), #8844 (same phone error on Windows, maybe the same PATH issue).