majorwiki/05-troubleshooting/iphone-mirroring-connecting-hang-awdl-stall-beta.md

141 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "iPhone Mirroring Hangs on 'Connecting…' — AWDL Data Stall (27.0 Beta)"
domain: troubleshooting
category: macos
tags: [macos, iphone-mirroring, continuity, awdl, rapport, quic, tailscale, mullvad, beta, channel-validation, aimesh, quicktime, usb]
status: published
created: 2026-06-09
updated: 2026-06-14
---
# iPhone Mirroring Hangs on 'Connecting…' — AWDL Data Stall (27.0 Beta)
## Update 20260614 — root cause refined (and what is *not* the cause)
> Reinvestigated endtoend on the **same OS seed** (build `26A5353q`, unchanged). The original "AWDL data stall / nothing local was wrong" call was close but misattributed the secondary causes. Corrected understanding below — **practical outcome is unchanged: no userside fix, wait for a new seed.**
**Refined root cause — the AWDL _bulkdata_ path can't hold a 5 GHz channel.**
Pulled the iPhone's own logs over USB (`sudo log collect --device --last 8m --output ~/Desktop/x.logarchive`). The kernel WiFi driver (`AppleBCMWLAN`, `wlan0:com.apple.p2p.awdl0`) shows, over 8 min on infra channel 36:
- `isValidChannel … not match … channel 36 band 0x10`**238×** (vs 32 passes): AWDL rejects the channel for the P2P group.
- `Disable Steering on Timeout`**159×**: can't steer to a better channel.
- `isInfraRealtimePacketThresholdAllowed allowed:0`**169/451**: bulk realtime packets blocked ~37 % of the time.
Net: the Mac's `awdl0` carries **~90 B/s** (control keepalive only; real video is hundreds of KB/sMB/s). The feed is **starved, not corrupted** — "missing icons" = frame data that never arrived (zero decode/`kVT` errors logged).
**What is NOT the cause (each tested and ruled out):**
- **Tailscale is not a hard RF blocker.** With acceptroutes on but **no exit node**, mirroring connects. Tailscale only *intermittently* breaks the **control plane** (QUIC endpoint binding → "Connection Interrupted"); with Tailscale **off** the session establishes but the **bulk video still starves**. So the old "disable Tailscale" step lets you *connect* but does **not** fix the video. (Mechanism is controlplane endpoint flapping, not the RFlayer block the original note implied.)
- **Not congestion.** Router `chanim_stats` on ch36 = **90 % idle, 86 % txop, 3 % obss**; Mac link 39 dBm / 94 dBm noise. Pristine.
- **Not the channel number — the whole UNII1 block is AWDLhostile on this seed.** ch36 → starved feed (~90 B/s, glitchy). **ch44** (same 3648 block) → **worse**: times out before media starts (`Failed to find endpoint`, `MediaContinuityKit.TaskTimeoutError`, 0 B/s). Both fail → the validator rejects the entire UNII1 block, not just primary 36.
- **ch149 (UNII3) untested.** It's the iPhone's preferred AWDL anchor and a *different* block, so it's the one channel that might work — but it's busier and the AiMesh controller resists pinning it (see infra notes). Deferred as not worth the disruption for a beta bug.
**Wired workaround (works today, no AWDL):**
iPhone Mirroring is **wirelessonly — 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** = fullrate USBC screen mirror (view + record). Does **not** give remote control (tap/type) — that's unique to iPhone Mirroring.
**Infra notes (RTAX82U, AiMesh controller):**
- Router SSH is on **port 1025** (not 22); creds in Ansible vault (`router_username` / `router_password`).
- The 5 GHz channel is **AiMeshcoordinated** and **resists CLI changes**`wl chanspec` / nvram `wl1_chanspec` get reasserted by `acsd2` + AiMesh within seconds, even after `restart_wireless`. Only setting Control Channel to an **explicit value in the Web UI** holds meshwide. Left "Auto" → acsd2 picks **36** (the cleanest channel).
- Any channel change triggers a **mesh resync (~1 min) that drops all WiFi**; during it MajorAir falls back to the iPhone's **USB Personal Hotspot** (`en7` / `172.20.10.x`) and won't autorejoin home WiFi while the hotspot feeds it internet (manual WiFimenu join needed).
- **Current state: 5 GHz on ch44/80** (same clean UNII1 spectrum as 36; left here to avoid another resync — the Deck streams identically on 44).
**Revisit checklist — when a new iOS/macOS seed ships:**
1. Confirm the seed changed: `sw_vers` BuildVersion ≠ `26A5353q` (both Mac and iPhone).
2. Tailscale **off**; iPhone on home WiFi, near the Mac, **Personal Hotspot off**.
3. Open iPhone Mirroring.
4. Measure `awdl0` RX over a few seconds — **target hundreds of KB/s** (real video), not ~90 B/s.
5. Pull the iPhone log (`log collect --device`) and check `isValidChannel` now **passes** for the infra channel.
6. If still starved → no user fix; refile Feedback Assistant and keep waiting.
---
## 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)
```bash
# 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
```
## Related
- `macos-mirrored-notification-alert-loop.md` (other Continuity issue)
- Hosts/VPN context: MajorTwin project doc (Tailscale tailnet, 100.x addresses)