Skip to content

iPhone Mirroring Hangs on 'Connecting…' — AWDL Data Stall (27.0 Beta)

Update 2026‑06‑15 — REGRESSED; reproducibly stuck on "Connecting", and Tailscale was not the cure

Correction to the 2026‑06‑14 "it WORKS" update below. On 2026‑06‑15 iPhone Mirroring is reproducibly stuck on "Connecting to iPhone 16 Pro" on MajorAir again — with Tailscale accept-routes still false. So the accept‑routes change was correlation, not the fix: this is an intermittent macOS 27.0 beta AWDL bug, independent of Tailscale.

Tried this round — all failed to establish a session: Tailscale accept-routes=false (already in place) · sudo ifconfig awdl0 down/up · full Mac reboot · cycling the iPhone's Wi‑Fi + Bluetooth.

Log signature: rapportd resolves the phone's _asquic._udp.local endpoint and _companion-link registers (discovery succeeds), but the QUIC‑over‑AWDL datapath never completes into a live session — wifip2pd loops on AWDLDiscoveryTimeout (hasAdvertises=false). Each reset advanced the handshake one stage further (no‑advertises → resolve‑started → endpoint‑resolved) yet none reached a streaming session. llw0 never went active (0 bytes) — confirming no A/V ever flowed, regardless of what the 06‑14 note measured.

Stance: beta OS bug, no reliable user‑side fix. Use the QuickTime USB mirror workaround (below) when you actually need the phone on screen. The 06‑14 "it works on llw0" measurements were real for that one session but are not reproducible across seeds/sessions — treat mirroring as intermittently broken on the 27.0 betas. This re‑confirms the original Root cause (conclusion) section further down (a beta bug, "nothing in local config wrong"), which the 06‑14 update had prematurely overridden.

Update 2026‑06‑14 (evening) — it WORKS; the "AWDL starvation" finding was the wrong interface

iPhone Mirroring is now working on MajorAir — stable session, clean video, no missing icons — on ch44/80 with Tailscale accept-routes=false. An earlier pass the same day blamed an "AWDL bulk‑path starving at ~90 B/s"; that was measuring the wrong interface and is corrected here.

The video transport is llw0 (low‑latency WLAN), not awdl0. Measured during an active session: llw0 ≈ 800 KB/s (≈6 Mbps of real video), en0 ~60 KB/s, awdl0 ~1 KB/s. awdl0 only ever carries AWDL discovery/control (~90 B/s) — whether mirroring works or not. So "90 B/s on awdl0 = starved bulk path" was a red herring: the A/V stream rides llw0, which the earlier pass never measured.

What was actually broken was session stability. The XPC_ERROR_CONNECTION_INTERRUPTED / MediaContinuityKit.TaskTimeoutError teardown loop kept the llw0 stream from ever sustaining (→ glitchy / missing icons). When the session holds, llw0 streams clean.

What changed (not cleanly isolated): three things differed between the broken and working states — (1) the network fully settled on ch44 over ~15 h (the failing ch44 test was minutes after a chaotic AiMesh re‑sync + reconnect scramble), (2) Tailscale accept-routes was turned off (it had been polluting IPv4 routing + the Continuity control plane), and (3) both devices slept/woke. Which one mattered is not yet proven.

Open test — isolates Tailscale's role: repro on MajorMac with unaltered Tailscale (accept-routes still ON). If mirroring breaks there but works on MajorAir (accept‑routes OFF), that pins Tailscale's accepted routes as the trigger. See MajorAir#Known Issues for the accept-routes=false fix.

Still valid from earlier today: congestion ruled out (router chanim_stats ch36 = 90 % idle, 86 % txop); the AiMesh / router infra notes below; and iPhone Mirroring is wireless‑only — no USB transport (for a wired screen view, use QuickTime, below).

⚠️ The iPhone‑radio isValidChannel/awdl0 evidence cited in the original 2026‑06‑09 write‑up below describes AWDL discovery health, not the video path — read it in light of this correction.

Wired workaround (works today, no AWDL): iPhone Mirroring is wireless‑only — there is no USB transport (confirmed: cable connected throughout, every attempt still used awdl0). For a wired view of the screen:

QuickTime Player → File → New Movie Recording → ⌄ next to record → select the iPhone = full‑rate USB‑C screen mirror (view + record). Does not give remote control (tap/type) — that's unique to iPhone Mirroring.

Infra notes (RT‑AX82U, AiMesh controller): - Router SSH is on port 1025 (not 22); creds in Ansible vault (router_username / router_password). - The 5 GHz channel is AiMesh‑coordinated and resists CLI changes — wl chanspec / nvram wl1_chanspec get re‑asserted by acsd2 + AiMesh within seconds, even after restart_wireless. Only setting Control Channel to an explicit value in the Web UI holds mesh‑wide. Left "Auto" → acsd2 picks 36 (the cleanest channel). - Any channel change triggers a mesh re‑sync (~1 min) that drops all Wi‑Fi; during it MajorAir falls back to the iPhone's USB Personal Hotspot (en7 / 172.20.10.x) and won't auto‑rejoin home Wi‑Fi while the hotspot feeds it internet (manual Wi‑Fi‑menu join needed). - Current state: 5 GHz on ch44/80 (same clean UNII‑1 spectrum as 36; left here to avoid another re‑sync — the Deck streams identically on 44).

If it breaks again — troubleshooting checklist: 1. It's session stability, not bandwidth. Look for teardown loops: log show --last 3m --predicate 'process == "iPhone Mirroring"' | grep -iE "interrupt|timeout|endpoint". 2. Measure the right interface — video rides llw0 (hundreds of KB/s when the screen is active), not awdl0 (~90 B/s control is normal): netstat -ib | awk '/<Link#/{print $1, $7}' before/after a few seconds. 3. Tailscale: confirm accept-routes=false on the Mac (tailscale debug prefs | grep RouteAll) — see MajorAir#Known Issues. 4. Let the network settle after any Wi‑Fi/channel change — an AiMesh re‑sync churns AWDL/Continuity state for a minute+; retry once stable. 5. iPhone: on home Wi‑Fi, near the Mac, Personal Hotspot off, not in Low Power Mode. 6. Wired fallback that always works: QuickTime → New Movie Recording → select the iPhone (USB‑C; view/record only, no control).


Symptom

iPhone Mirroring on the Mac sits on "Connecting…" forever and never shows the iPhone screen. - Mac: macOS 27.0 dev beta (build 26A5353q), MajorAir - iPhone: Major16Pro / iPhone17,1, iOS 27.0 dev beta, same Apple ID (maj.linux@gmail.com)

Root cause (conclusion)

A bug in the iPhone Mirroring beta (both devices on the .0 developer seeds). The connection authenticates, the AWDL peer-to-peer link comes up, the TLS handshake starts — then bidirectional data stalls ~2 seconds in and the link is torn down. Deterministic, reproduces every attempt. Nothing in the local configuration was wrong. Filed via Feedback Assistant; expected to clear in a future seed.

Two real but secondary network-layer issues were found and fixed along the way (see below) — they can block mirroring independently, but were not the cause of the final 2-second stall.

The smoking gun (unified log)

Per connection attempt the sequence is always:

rapportd: Session start … linkType "AWDL", error "NoError"      # link negotiated OK
iPhone Mirroring: Installing verify block for 1 authorized peer key(s)
boringssl: TLS client read_server_hello                          # iPhone DID respond
quic: path over awdl0 received event established / promoted to primary
nw_flow_connected: Transport protocol connected (socket)
… flow:connect_stalled @2.003s                                  # stalls exactly ~2s in
quic_conn_log_summary: Connection attempts: 6, RETRY received: no, PTOs: 5   # packets sent, zero ACKs
[C1.1.1 … awdl0 … failed socket-flow (unsatisfied (No network route))]      # link dropped (symptom, not cause)
The connection is pinned to AWDL (allowed subtypes: wifi_awdl, prohibit fallback), so once the AWDL data path stalls there is no fallback and it fails. "No network route" is the result of the teardown, not the trigger. The trigger is that after the initial handshake packets, sustained QUIC traffic over AWDL gets no ACKs (PTOs).

Investigation path (what was ruled out)

  • Discovery / proximity — healthy throughout. BLE + Bonjour resolve the iPhone; rapportd sees it with good RSSI, same iCloud (DF < MyiCloud >), WiFiP2P.
  • Tailscale (full-tunnel) — with Tailscale connected, the attempt died at "No network route" before even reaching AWDL. Cause: RouteAll: true (accept-routes / a ::/0 advertised route) installs IPv6 default routes via utun (default → fe80::%utun0..3) that black-hole the IPv6 path AWDL needs. tailscale down is NOT enough — it only sets WantRunning=false; the macOS VPN configuration (scutil --nc list showed it still Connected) and the system extension keep reasserting the routes across reboots. Must disable in System Settings → VPN.
  • Mullvad — mullvad-daemon running; "Local network sharing" was set to block, which blocks LAN/AWDL/multicast. Changed to allow (mullvad lan set allow). Kill-switch was off.
  • macOS firewall — off. No Little Snitch/LuLu app installed.
  • Lockdown Mode — off (iPhone).
  • OS-version mismatch — ruled out; both Mac and iPhone on 27.0 dev beta.
  • Device trust / re-pairing — there is no local pairing record on the Mac to reset. rapportd lists the iPhone as "PairedSys Conjectured" = trust is derived from the shared Apple ID, not a manual pairing. Forgetting the Mac on the iPhone does not force re-setup; the Mac just re-derives the association from iCloud and reconnects. (App containers ~/Library/Containers/com.apple.ScreenContinuity and the rapport stores held no device record; the "1 authorized peer key" lives in the protected system keychain.)
  • Reboots / airplane-mode toggle / Mac-side AWDL + rapportd reset — no change.

Secondary issues found & fixed (do these regardless)

  1. Mullvad — set Local network sharing = allow (done). Required for any LAN/AWDL feature.
  2. Tailscale — do not run full-tunnel / accept a ::/0 route while mirroring; it installs IPv6 default routes via utun that kill the local link. Toggle the VPN off in System Settings (not just tailscale down) if it ever needs to be fully out of the path.
  3. Orphaned Little Snitch network extension — the app was uninstalled but its at.obdev.littlesnitch.networkextension is still [activated enabled] (systemextensionsctl list). Remove via System Settings → General → Login Items & Extensions → Network Extensions. A zombie filter extension with no app behind it can black-hole traffic.

Status / next steps

  • No user-side fix. Filed in Feedback Assistant.
  • Debug capture saved: ~/Desktop/iPhoneMirroring-debug-20260609-0026.txt (summary + log narrative). For a full report, trigger a sysdiagnose (⌃⌥⇧⌘ + .) right after reproducing and attach it.
  • VPNs restored after session: Tailscale back up; Mullvad left disconnected with LAN sharing = allow.

Useful diagnostic commands (for next time)

# Connection narrative
log show --last 10m --style compact --predicate \
  '(subsystem == "com.apple.MediaContinuityKit") OR (process == "iPhone Mirroring")' | tail -60
# rapport / AWDL negotiation
log show --last 5m --style compact --predicate 'process == "rapportd"' | grep -iE "AWDL|Pair|Session"
# VPN config really on? (CLI "down" lies)
scutil --nc list ; scutil --nc status "Tailscale"
# IPv6 default routes hijacked by utun?
netstat -rn -f inet6 | awk '$1=="default"{print}'
# Active system extensions (filters/VPNs)
systemextensionsctl list
# Mullvad LAN sharing
mullvad lan get
  • macos-mirrored-notification-alert-loop.md (other Continuity issue)
  • Hosts/VPN context: MajorTwin project doc (Tailscale tailnet, 100.x addresses)