Skip to content

[Bug]: Quitting restarts the T3 Connect relay client mid-shutdown, adding about 2.3s to the backend stop #33623

Closed

Description

@ishaanko

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Run the desktop app with T3 Connect linked, so a relay client (cloudflared) is running, and with OpenCode installed.
  2. Launch the app and quit it within about 30 seconds (⌘Q).

The 30 seconds is only what makes it reliable today: the shared opencode serve process is still alive then, and stopping it takes a fixed second (#33621), which holds up every later shutdown step. Any shutdown step that runs ahead of the relay runtime's finalizer and takes longer than cloudflared's own exit (about 15ms here) opens the same window.

Expected behavior

Once the server starts shutting down, the relay client is stopped and stays stopped, and the backend exits promptly.

Actual behavior

The relay client is restarted in the middle of shutdown, registers with Cloudflare again, and is then killed while it is still connecting. That kill takes about 2.3 seconds. The backend stop took 4.3 to 4.4 seconds, close to the 5 second point where the desktop sends SIGKILL. The Dock icon stays running for that whole time after the window is gone.

What I think is happening, from the logs below and the code on main (bbdc7dc):

  1. The desktop stops the backend by signalling its process group. The relay client is spawned with detached: false (apps/server/src/cloud/ManagedEndpointRuntime.ts:746), so it is in that group and gets the SIGTERM directly. It exits cleanly about 15ms later.
  2. superviseConnector (same file, line 319) sees the exit. The desired config is still set, so it logs "Relay client exited; restarting" and spawns a replacement.
  3. The desired config is only cleared by the runtime's own finalizer, runtime.applyConfig(null) (line 915). That runs after the shutdown steps ahead of it, here about one second later. releaseManagedTunnelOnShutdown runs earlier, but it returns before applyConfig(null) for links it does not release.
  4. That finalizer then stops the replacement, which is mid-registration (2 of 4 connections up). The stop has no force-kill bound and waited 2.3 seconds for cloudflared to exit.

On quits where the finalizer ran before the supervisor saw the exit (no OpenCode server alive), there was no restart and the backend stopped in 49ms.

Impact

Minor bug or occasional failure

Version or commit

0.1.8-nightly.20261109.4433. Code references are to main @ bbdc7dc.

Environment

macOS 27.2 arm64, desktop app with its local server, managed relay client 2026.10.4.

Logs or stack traces

Two quits a few seconds after launch. Times are relative to the desktop starting to stop the backend (desktop.backendInstance.closeScope). Relay lines are from relay-client.ndjson, spans from server.trace.ndjson. Tunnel names, IDs and addresses removed.

Quit A (backend stop took 4323ms)
   +17ms  relay pid 25525: ERR Connection terminated connIndex=2 / 0 / 1 / 3
   +17ms  relay pid 25525: ERR no more connections active and exiting
   +21ms  Relay client stopped                       pid 25525
   +22ms  Relay client exited; restarting            pid 25525, exitCode 0
   +23ms  Relay client process started; waiting for tunnel connection   pid 25840
  +335ms  relay pid 25840: INF Registered tunnel connection connIndex=0
  +525ms  relay pid 25840: INF Registered tunnel connection connIndex=1
          span OpenCodeServerOwner.closeServer                +21ms -> +1024ms  (1003ms)
          span CloudManagedEndpointRuntime.applyConfig      +1032ms -> +3344ms  (2312ms)
 +3343ms  Relay client stopped                       pid 25840
          span AnalyticsService.sendBatch                   +3369ms -> +4293ms   (925ms)

Quit B (backend stop took 4385ms)
   +14ms  relay pid 26340: ERR no more connections active and exiting
   +16ms  Relay client exited; restarting            pid 26340, exitCode 0
   +20ms  Relay client process started; waiting for tunnel connection   pid 26647
          span OpenCodeServerOwner.closeServer                +18ms -> +1022ms  (1004ms)
          span CloudManagedEndpointRuntime.applyConfig      +1033ms -> +3351ms  (2318ms)
 +3350ms  Relay client stopped                       pid 26647

Quit with no OpenCode server alive (backend stop took 49ms)
          span CloudManagedEndpointRuntime.applyConfig        +15ms ->   +17ms    (2ms)
   +21ms  Relay client stopped                       pid 24299

Workaround

None found. Quitting more than 30 seconds after the last OpenCode use avoids the slow case on this machine.

Notes

  • Not checked: npx t3 and the background service. A terminal Ctrl+C also signals the whole foreground group, so I would expect the same restart there, but I have not run it.
  • Not checked: whether this still happens with perf(opencode): stopping an OpenCode server no longer always waits a full second #33621 applied. That PR removes the fixed second, but the relay finalizer would still run after cloudflared has exited whenever an OpenCode server has to be stopped first, so I expect the restart to remain.
  • I did not open a PR because the fix looks like a lifecycle decision rather than a small patch. Options I can see: clear the connector's desired config at the very start of shutdown, make the supervisor aware that the server is stopping, or at least bound how long stopping a connector can take.

Filed by Claude Fable 5.2 in Claude Code on behalf of Ishaan.

Activity

  1. shivamhwp commented on Nov 10, 2026

    @shivamhwp
    Collaborator

    [GPT-6.1 Sol][Codex] on behalf of shivam.

    Julius has taken this over in #33628, which closes this issue. Stopping this automated job here. No local changes or device tests were started.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions