Skip to content

[Bug]: Mobile wakeup health probe drops live sessions on high-RTT routes (Tailscale DERP, VPN, public) #24677

Closed

Description

@broomva

Before submitting

Area

apps/mobile (shared logic in packages/client-runtime)

Steps to reproduce

  1. Pair the iOS app with a desktop host over Tailscale, using the host's tailnet IP or MagicDNS name (not the T3 relay).
  2. Leave home WiFi so the phone is on cellular. In this setup the tailnet path ran through a DERP relay, whose round trips spike past 3 s: pong via DERP(mia) in 3.421s, then a timeout, then 160ms.
  3. Use the app normally: switch apps for a few seconds, pull down Control Center, receive notifications, move between cells.

It reproduces without a phone. Run the real EnvironmentSupervisor and RpcSessionFactory over a real WebSocket against a local t3 serve, through a TCP proxy that holds server→client bytes for 3.5 s. Pair each spike with an application-active-probe or network-changed wakeup:

Route kind Code Spikes Sessions replaced
tailnet (*.ts.net) main 6 6
tailnet with the fix below 6 0
LAN (192.168.x) with the fix below 2 2 (fast detection kept)

Expected behavior

A live session on a remote route survives a single slow round trip after a foreground or network-change wakeup, as it does on a LAN.

Actual behavior

The app keeps showing Reconnecting, then Syncing threads…. Host traces show the phone's /ws sessions living 6–45 s, each followed by a new wsTicket and a new session.

EnvironmentSupervisor probes the live session on application-active-probe (also fired on inactive → active) and on network-changed with QUICK_CONNECTION_PROBE_TIMEOUT (3 s), in probeTimeoutFor in packages/client-runtime/src/connection/supervisor.ts. A late reply replaces the session, which reloads the shell snapshot and marks threads synchronizing. Three seconds is reliable for loopback and LAN, not for DERP-relayed tailnet, VPN or public routes.

Impact

On the go, the mobile app is effectively unusable over Tailscale: the user only gets a stable session on the same WiFi as the host.

Version or commit

iOS app 2.0.0; desktop host 0.1.0 at the time of measurement; reproduced against main at 8f26ed7.

Environment

iPhone 16 Pro, iOS 26, cellular in Colombia. macOS host on wired Ethernet behind a router without UPnP/NAT-PMP, so Tailscale fell back to DERP.

Logs or stack traces

Host server trace: phone sessions ending after 45.0 s, 18.7 s (client abort, 499), 17.6 s and 45.0 s, each reconnect authenticating a fresh websocket ticket for the same session.

A fix that keeps the 3 s budget for loopback and LAN and uses the existing 15 s CONNECTION_PROBE_TIMEOUT elsewhere follows in a PR.


Prepared with Claude Opus 5.5 in Claude Code, at the user's request; the measurements were taken on the user's own host and phone.

Activity

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