tailscale / tailscale/tailscale
macOS: utun write stall (ENOSPC) persists until restart; daemon itself healthy
- Dominant language
- Go
- Stars
- 36.5k
- Forks
- 3.2k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 123
Description
## Version / platform
- Tailscale 1.102.4 (also observed on 1.102.3), Tailscale.app + system extension
(`io.tailscale.ipn.macsys.network-extension`)
- macOS 26.6.2 (Darwin 25.6.0), MacBookPro18,3 (arm64)
- Exit node in use (direct UDP path normally), CorpDNS on
## Symptom
At intervals, all connectivity through Tailscale dies at once: exit-node traffic,
tailnet traffic, and DNS via 100.100.100.100. WiFi stays associated; the radio is
fine. `tailscale status` reports BackendState `Running` throughout. Turning off only
the exit node does NOT recover (DNS still transits utun); only `tailscale down/up`
(or full toggle) recovers. 5+ episodes over 4 days (2026-09-11 x2, 2026-09-14 x3,
the latter all post-reboot on 1.102.4).
## Signature
Unified log, from `io.tailscale.ipn.macsys.network-extension`, thousands/min:
```
wg: Failed to write packets to TUN device: write /dev/tun: no space left on device
```
Zero occurrences on healthy days (checked 3+ days of retained logs); ~2.7k in the
onset minute, ~5.2–5.6k/min sustained while wedged. Preceded at onset by UDP path
flaps (`NetInfo udp=false`) and/or WiFi AP roam activity; never self-recovers
(observed stuck 8+ min until manual restart).
## Key finding: the daemon is exonerated
`tailscale debug daemon-goroutines` captured mid-wedge (LocalAPI responsive) vs a
healthy baseline are functionally identical: same goroutine count (~110), no
deadlock, no stuck mutex, TUN read loop (`tstun.Wrapper.pollVector` →
`NativeTun.Read`) parked normally in IO-wait, magicsock/control/DNS all in usual
states. Full dumps available on request (2x wedged, 1x healthy).
Conclusion: the clog is below the daemon — decrypted packets are written into
/dev/tun, the kernel refuses them (queue full), the daemon logs and drops. So
Apple's NE packet-delivery path has stopped consuming while the extension process
stays alive. `status` staying green is expected under this theory, and matches.
## Environment notes (possible contributors)
- System load spikes hard around episodes (15-min load avg 25–32; instantaneous
calm between). OS daemon CPU storms (Spotlight/mds, cloudd, fileproviderd,
WindowServer) bracket the evening episodes. CPU starvation of the extension's
packet threads is suspect #1.
- A second network extension (Intego NetBarrier firewall) was in the packet path
during all episodes; currently testing with it disabled — will update.
- Reboot does not prevent recurrence (3 stalls same day post-reboot).
## Ask
Is this a known failure mode of the macsys TUN/NE flow under load? Anything you'd
like captured during the next wedge beyond the goroutine dumps (happy to run
`tailscale bugreport` mid-outage)?
---
*Diagnosed with AI assistance; full unified-log excerpts, daemon goroutine dumps
(wedged x2, healthy baseline), and per-episode timelines available on request.*
Contributor guide
Research direction
Start with the reported unified-log signature from io.tailscale.ipn.macsys.network-extension and capture tailscale bugreport plus daemon-goroutines during the next wedge. Compare the wedged and healthy dumps, including tstun.Wrapper.pollVector and NativeTun.Read, and correlate them with UDP path, WiFi, system load, and the Intego extension. Done means identifying a reproducible failure or a supported diagnostic path for the stalled NE packet flow.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, macos
- Domain
- networking, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100