Duplicate of #16549, which tracks the iOS app reconnect-loop through Tailscale Serve after successful authentication, including when the server produces configuration promptly. The traces here add evidence on iOS 2.1.0: reconnects continue after the host CLI timeout is resolved. Keeping the investigation in the original issue.
[Bug]: iOS app reconnect-loops and threads stay on Syncing over Tailscale Serve on an intermittent connection#24909
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/mobile
Steps to reproduce
- Run the server as the background service on macOS, bound to
127.0.0.1:3773and reached through Tailscale Serve. The iPhone app is the only client. - Open the iOS app on a slow or intermittent connection.
- Open a thread.
Expected behavior
The environment stays connected, and the thread loads.
Actual behavior
The environment flips between connected and disconnected. An opened thread often stays on "Syncing". When it loads, it first shows an older cached state, then the newer messages. How this goes varies by thread.
Server traces (2026-10-25, UTC). All 50 Tailscale /ws sockets came from this phone (clientSurface=mobile, clientAppVersion=2.1.0, iOS 27, connectionMethod=direct):
- Median socket life was 62 s, and 43 of 50 lasted 120 s or less. Upgrade auth succeeded every time.
- In 28 of 49 reconnects, the phone opened the new socket while the server still held the old one (median overlap 21 s).
- 16 of 50 sockets sent no RPC after
subscribeServerConfig. - Thread snapshots took 0.1–0.4 s on the server.
- Each
subscribeServerConfigspent about 3.5 s inws.loadServerConfig, waiting ontailscale.readTailscaleOutput. All 50 calls failed withTailscaleCommandTimeoutError: tailscale status timed out after 3500ms. On this host thetailscaleCLI couldn't reach the daemon's socket.
After the host CLI could reach the daemon (16:51–16:55Z, same versions), ws.loadServerConfig took 0.4–1.4 s. The drops continued: sockets lasted 101 s, 71 s and 0 s, with the same overlap.
The iOS app exposes startup crash logs only, not runtime logs, so this is server-side evidence only. No startup crash was recorded. I didn't measure the phone's network or whether its Tailscale path was direct or DERP.
Impact
Major degradation or frequent failure
Version or commit
Server t3 0.1.3-nightly.20261023.3579; iOS app 2.1.0 (164)
Environment
macOS host, Tailscale Serve (userspace tailscaled); iPhone, iOS 27.0.1
Logs or stack traces
| 1 | server.trace.ndjson, UTC, offsets from /ws upgrade (hosts, tickets, IPs removed) |
| 2 | |
| 3 | 15:25:00Z /ws 101 life=25.8s |
| 4 | +0.9s subscribeServerConfig 19.93s Interrupted (loadServerConfig ~3.5s: tailscale status timeout) |
| 5 | no other RPC |
| 6 | +25.8s markDisconnected |
| 7 | 15:25:28Z /ws 101 life=85.5s (opened 1.9s before the server closed the previous socket) |
| 8 | +0.9s subscribeServerConfig 83.78s Interrupted |
| 9 | +10.0s first other RPCs |
| 10 | +11.7s orchestration.subscribeShell 73.01s Interrupted |
| 11 | +85.5s markDisconnected |
| 12 | |
| 13 | 14:26:45Z /ws 101 life=2735.6s (longest socket) |
| 14 | +0.8s subscribeServerConfig |
| 15 | +8.7s first other RPCs |
Related
#24677 (iOS on a high-latency Tailscale route, wakeup probe replacing sessions), #24192 (mobile thread view on Syncing), #16549, #23731, #14519.