cloudflare/quiche · error · io::Error

InvalidInput

InvalidInput

Error message

Must provide a <host:port> to connect

What it means

h3i's Config::build validates that a host:port target was set before constructing the Config. If host_port is empty, it refuses to build and returns InvalidInput, because h3i cannot know where to connect.

Solutions

  1. Call with_host_port("host:port") before build()
  2. If driving h3i from a CLI, pass the required --host argument
  3. Validate the host:port string is non-empty before constructing Config

Example fix

// before
let config = Config::new().build()?; // panics-free error: empty host_port
// after
let config = Config::new().with_host_port("quic.nginx.org:443").build()?;
Defensive patterns

Strategy: validation

Validate before calling

if host_port.is_empty() {
    return Err(io::Error::new(io::ErrorKind::InvalidInput, "host:port required"));
}
let config = Config::new().with_host_port(host_port).build()?;

Type guard

fn has_host_port(cfg: &ConfigBuilder) -> bool { !cfg.host_port().is_empty() }

Try / catch

match config.build() {
    Err(e) if e.kind() == io::ErrorKind::InvalidInput => eprintln!("--host <host:port> is required"),
    other => other?,
}

Prevention

When it happens

Trigger: Calling Config::build() on h3i::config::Config without having called with_host_port (or equivalent), leaving host_port empty.

Common situations: Programmatic use of the h3i crate where the CLI normally supplies --host <host:port>; forgetting the host_port argument; parsing a CLI string into an empty value.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at h3i/src/config.rs:177

    }

    pub fn with_dgram_recv_queue_len(
        mut self, dgram_recv_queue_len: usize,
    ) -> Self {
        self.dgram_recv_queue_len = dgram_recv_queue_len;
        self
    }

    pub fn with_dgram_send_queue_len(
        mut self, dgram_send_queue_len: usize,
    ) -> Self {
        self.dgram_send_queue_len = dgram_send_queue_len;
        self
    }

    pub fn build(self) -> Result<Self, io::Error> {
        if self.host_port.is_empty() {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Must provide a <host:port> to connect".to_string(),
            ));
        }

        Ok(Config {
            host_port: self.host_port,
            omit_sni: self.omit_sni,
            connect_to: self.connect_to,
            source_port: self.source_port,
            verify_peer: self.verify_peer,
            idle_timeout: self.idle_timeout,
            max_data: self.max_data,
            max_stream_data_bidi_local: self.max_stream_data_bidi_local,
            max_stream_data_bidi_remote: self.max_stream_data_bidi_remote,
            max_stream_data_uni: self.max_stream_data_uni,
            max_streams_bidi: self.max_streams_bidi,
            max_streams_uni: self.max_streams_uni,

View on GitHub (pinned to 9f96daa2c2)