cloudflare/quiche · error

--connect-to is expected to be a string containing an IPv4…

Error message

--connect-to is expected to be a string containing an IPv4 or IPv6 address with a port. E.g. 192.0.2.0:443

What it means

quiche-client validates the --connect-to CLI value by parsing it directly with expect(), which panics if the string is not a valid SocketAddr (an IP:port literal, not a hostname). The panic message instructs the user on the expected format.

Solutions

  1. Pass a literal IP with port, e.g. --connect-to 192.0.2.0:443
  2. Resolve the hostname externally (dig/host) and use the resulting IP
  3. Patch the code to resolve hostnames before parse if you control the build

Example fix

// before
quiche-client --connect-to example.com:443 https://example.com/
// after
quiche-client --connect-to 93.184.216.34:443 https://example.com/
Defensive patterns

Strategy: validation

Validate before calling

let addr: std::net::SocketAddr = connect_to.parse().map_err(|_|
    anyhow!("--connect-to must be an IPv4/IPv6 address with port, e.g. 192.0.2.0:443"))?;

Type guard

fn is_socketaddr_literal(s: &str) -> bool {
    s.parse::<std::net::SocketAddr>().is_ok()
}

Prevention

When it happens

Trigger: Running quiche-client with --connect-to set to something like example.com:443 (a hostname) or a malformed address like 192.0.2.0 (missing port) — addr.parse::<SocketAddr>() fails in connect().

Common situations: Users assuming --connect-to accepts DNS names (it requires literal IPs); typos or missing port; copying curl-style --connect-to syntax which differs.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


AI-assisted analysis of cloudflare/quiche@9f96daa2c2 (2026-09-08). Data as JSON: /api/errors/925228532a778069. Report an issue: GitHub.

Appendix: source

Thrown at apps/src/client.rs:66

    args: ClientArgs, conn_args: CommonArgs,
    output_sink: impl FnMut(String) + 'static,
) -> Result<(), ClientError> {
    let mut buf = [0; 65535];
    let mut out = [0; MAX_DATAGRAM_SIZE];

    let output_sink =
        Rc::new(RefCell::new(output_sink)) as Rc<RefCell<dyn FnMut(_)>>;

    // Setup the event loop.
    let mut poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    // We'll only connect to the first server provided in URL list.
    let connect_url = &args.urls[0];

    // Resolve server address.
    let peer_addr = if let Some(addr) = &args.connect_to {
        addr.parse().expect("--connect-to is expected to be a string containing an IPv4 or IPv6 address with a port. E.g. 192.0.2.0:443")
    } else {
        *connect_url.socket_addrs(|| None).unwrap().first().unwrap()
    };

    // Bind to INADDR_ANY or IN6ADDR_ANY depending on the IP family of the
    // server address. This is needed on macOS and BSD variants that don't
    // support binding to IN6ADDR_ANY for both v4 and v6.
    let bind_addr = match peer_addr {
        std::net::SocketAddr::V4(_) => format!("0.0.0.0:{}", args.source_port),
        std::net::SocketAddr::V6(_) => format!("[::]:{}", args.source_port),
    };

    // Create the UDP socket backing the QUIC connection, and register it with
    // the event loop.
    let mut socket =
        mio::net::UdpSocket::bind(bind_addr.parse().unwrap()).unwrap();
    poll.registry()
        .register(&mut socket, mio::Token(0), mio::Interest::READABLE)

View on GitHub (pinned to 9f96daa2c2)