nautechsystems/nautilus_trader · error · Error::Io(std::io::Error)

Request URI missing host component

Error message

Request URI missing host component

What it means

The rustls TLS connector derives the server name for SNI/certificate verification from the request URI. If the URI has no host component, `domain` cannot produce a server name and returns an `InvalidInput` error. IPv6 hosts are handled by stripping the surrounding brackets, but an absent host is fatal.

Source

Thrown at crates/network/src/tls.rs:83

                .map_err(|_| TlsError::InvalidDnsName)?
                .to_owned();
            let stream = TlsConnector::from(config).connect(domain, socket).await?;
            Ok(MaybeTlsStream::Rustls(stream))
        }
    }
}

/// Extracts the host name from the request URI.
///
/// # Errors
///
/// Returns an error if the request URI has no host component.
fn domain(request: &Request) -> Result<String, Error> {
    match request.uri().host() {
        // rustls expects IPv6 addresses without the surrounding [] brackets
        Some(d) if d.starts_with('[') && d.ends_with(']') => Ok(d[1..d.len() - 1].to_string()),
        Some(d) => Ok(d.to_string()),
        None => Err(Error::Io(std::io::Error::new(
            std::io::ErrorKind::InvalidInput,
            "Request URI missing host component",
        ))),
    }
}

pub(crate) fn create_tls_config_from_certs_dir(
    certs_dir: &Path,
    require_client_auth: bool,
) -> anyhow::Result<rustls::ClientConfig> {
    install_cryptographic_provider();

    if !certs_dir.is_dir() {
        anyhow::bail!(
            "Certificate path is not a directory: {}",
            certs_dir.display()
        );
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the request URI includes a host (e.g. `wss://stream.example.com/ws`).
  2. Validate the endpoint string is non-empty and contains a host before building the request.
  3. If using an IP, note IPv6 must be provided (brackets are stripped automatically); IPv4 literals are fine.

Example fix

// before
let uri = "wss:///stream"; // no host
// after
let uri = "wss://stream.example.com/stream";
Defensive patterns

Strategy: validation

Validate before calling

fn uri_has_host(req: &Request) -> bool {
    req.uri().host().map(|h| !h.is_empty()).unwrap_or(false)
}

Try / catch

if !uri_has_host(&request) {
    return Err("endpoint must include a host, e.g. wss://host/path".into());
}
let stream = tcp_tls(request).await?;

Prevention

When it happens

Trigger: Constructing a TLS (wss/https) request whose URI lacks a host — e.g. `wss:///path`, an empty endpoint string, or a URI object built with only a path/query — then passing it to `tcp_tls`.

Common situations: Endpoints assembled programmatically where the host variable was empty, misconfigured environment variables, or default-constructed request URIs passed to the TLS connector.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/43889ff3bd09cbb7. Report an issue: GitHub.