n0-computer/iroh · critical · io::Error

NetworkDown

NetworkDown

Error message

All transports failed to receive

What it means

The QUIC socket's transport poll_recv loop hit MAX_CONSECUTIVE_RECV_ERRORS consecutive receive failures across all transports. The endpoint concludes the network is down, returns io::ErrorKind::NetworkDown, and shuts the QUIC endpoint down rather than spinning forever on errors.

Solutions

  1. Recreate/restart the Endpoint (and its sockets) when NetworkDown is returned; it is designed to signal a full teardown.
  2. Diagnose why the underlying transports fail to recv: check interface state, permissions, and firewall rules.
  3. Retry application-level connection attempts with backoff after the network recovers.
  4. Monitor the warn! log ('All transports failed to receive') to correlate with environment changes.

Example fix

// before
let conn = endpoint.connect(addr, alpn).await?; // fails after NetworkDown teardown
// after
match endpoint.connect(addr, alpn).await {
    Ok(c) => c,
    Err(e) if e.kind() == NetworkDown => { endpoint = recreate_endpoint().await?; endpoint.connect(addr, alpn).await? }
    Err(e) => return Err(e.into()),
}
Defensive patterns

Strategy: retry

Type guard

fn is_network_down(e: &std::io::Error) -> bool { e.kind() == std::io::ErrorKind::NetworkDown }

Try / catch

match ep_transport_recv() {
    Err(e) if e.kind() == std::io::ErrorKind::NetworkDown => { rebuild_endpoint_with_backoff().await?; }
    other => other?,
}

Prevention

When it happens

Trigger: poll_recv repeatedly returning errors for every transport (relay and UDP) MAX_CONSECUTIVE_RECV_ERRORS times in a row — e.g. sockets closed underneath, OS network interface flapping, all underlying transports erroring on recv.

Common situations: Laptop suspending/resuming or interface changes killing UDP sockets, containers losing their network namespace, firewall/VPN changes breaking all local transports, running in environments where UDP is blocked and the relay transport also fails.

Related errors


AI-assisted analysis of n0-computer/iroh@2b4de030ce (2026-09-08). Data as JSON: /api/errors/7a1608d34c23ddbd. Report an issue: GitHub.

Appendix: source

Thrown at iroh/src/socket/transports.rs:351

            for transport in self.relay.iter_mut().rev() {
                poll_transport!(transport);
            }
            #[cfg(not(wasm_browser))]
            for transport in self.ip.iter_mut() {
                poll_transport!(transport);
            }
        }

        if total_polled == total_errors {
            // All transports errored.
            self.consecutive_total_recv_failures += 1;
            debug!(
                "All transports failed to receive ({} remaining)",
                MAX_CONSECUTIVE_RECV_ERRORS.wrapping_sub(self.consecutive_total_recv_failures)
            );
            if self.consecutive_total_recv_failures >= MAX_CONSECUTIVE_RECV_ERRORS {
                warn!("All transports failed to receive. QUIC endpoint will be shutdown.");
                Poll::Ready(Err(io::Error::new(
                    io::ErrorKind::NetworkDown,
                    "All transports failed to receive",
                )))
            } else {
                Poll::Ready(Ok(0))
            }
        } else {
            // At least one transport is pending or returned Ok(0).
            self.consecutive_total_recv_failures = 0;
            if return_ready {
                Poll::Ready(Ok(0))
            } else {
                Poll::Pending
            }
        }
    }

    /// Returns a list of all currently known local addresses.

View on GitHub (pinned to 2b4de030ce)