---
name: broken-ipv6-poisons-iroh-discovery
description: "A host with half-broken IPv6 (AAAA resolves, IPv6 path dead) silently fails to join an spt subnet — iroh dual-stack discovery/meet burns the rendezvous window on dead IPv6 candidates"
metadata: 
  node_type: memory
  type: reference
  originSessionId: 712ec375-e0f7-42d6-afab-1b6b84a87330
---

**Symptom:** a machine "never finds a machine" joining an spt subnet over WAN, then silently stops — no error. Occasionally reaches "Wrong code (codes rotate every 30s)" after a long wait (slow meet → the typed code went stale). Intermittent.

**Root cause (diagnosed + CONFIRMED 2026-06-27, SCELTOUIN):** **half-broken IPv6** — the host resolves AAAA records and *attempts* IPv6, but its IPv6 path is dead (no route). spt's iroh endpoint (N0 preset) binds **dual-stack** and attempts both families for n0 discovery (`dns.iroh.link`) and the rendezvous hole-punch; dead-IPv6 attempts don't refuse — they **silently time out**, consuming the 30s-rotating rendezvous window (search deadline 75s, `pairhost.rs` SEARCH_DEADLINE). Usually times out silently; occasionally meets slowly → stale code.

**The one-command tell:** `Test-NetConnection dns.iroh.link -Port 443` shows TCP to the **AAAA (IPv6) addr FAILS** but the **A (IPv4) addr succeeds**. (dns.iroh.link = the n0 DISCOVERY service, separate from the n0 RELAY `use1-1.relay.iroh.network` — relay can be reachable while discovery's IPv6 leg is dead.)

**Fix / confirm:** disable IPv6 on the active adapter → join succeeds instantly. `Disable-NetAdapterBinding -Name "Wi-Fi" -ComponentID ms_tcpip6` (revert: `Enable-NetAdapterBinding`).

**Refuted cheaply first (don't chase):** clock skew + ceremony-NTP (`now_secs`=`ntp::ceremony_now_secs`, silent `unwrap_or(0)` fallback on no NTP — but clock was +0.09s, NTP fine); Windows firewall (installer adds "spt-core inbound UDP" Allow Profile Any); n0 relay reachability (fine). Each a one-liner.

**spt-core findings (→ [[spt-core-findings-backlog]]):** (1) discovery not resilient to half-broken IPv6 — want happy-eyeballs fast-IPv4-fallback / IPv6-health gating / shorter IPv6 timeout / an SPT_DISABLE_IPV6 knob (mirror SPT_NTP_SERVER). (2) SILENT-UX: `connect_seed_holder` (pairhost.rs:437) + `dial_via_rendezvous` (meet.rs:281) swallow every probe error; `brain.rs:1024` `_=>continue` can hide the terminal event — a window-exhausted join must report why (candidates/families tried, last error). Known kin: docs/DEFERRED.md row 23 (firewall) + row 30 (clock) are the OTHER two silent join-failure traps.
