{"record":{"id":"43889ff3bd09cbb7","repo":"nautechsystems/nautilus_trader","slug":"request-uri-missing-host-component","errorCode":null,"errorMessage":"Request URI missing host component","messagePattern":"Request URI missing host component","errorType":"validation","errorClass":"Error::Io(std::io::Error)","httpStatus":null,"severity":"error","filePath":"crates/network/src/tls.rs","lineNumber":83,"sourceCode":"                .map_err(|_| TlsError::InvalidDnsName)?\n                .to_owned();\n            let stream = TlsConnector::from(config).connect(domain, socket).await?;\n            Ok(MaybeTlsStream::Rustls(stream))\n        }\n    }\n}\n\n/// Extracts the host name from the request URI.\n///\n/// # Errors\n///\n/// Returns an error if the request URI has no host component.\nfn domain(request: &Request) -> Result<String, Error> {\n    match request.uri().host() {\n        // rustls expects IPv6 addresses without the surrounding [] brackets\n        Some(d) if d.starts_with('[') && d.ends_with(']') => Ok(d[1..d.len() - 1].to_string()),\n        Some(d) => Ok(d.to_string()),\n        None => Err(Error::Io(std::io::Error::new(\n            std::io::ErrorKind::InvalidInput,\n            \"Request URI missing host component\",\n        ))),\n    }\n}\n\npub(crate) fn create_tls_config_from_certs_dir(\n    certs_dir: &Path,\n    require_client_auth: bool,\n) -> anyhow::Result<rustls::ClientConfig> {\n    install_cryptographic_provider();\n\n    if !certs_dir.is_dir() {\n        anyhow::bail!(\n            \"Certificate path is not a directory: {}\",\n            certs_dir.display()\n        );\n    }","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/network/src/tls.rs#L65-L101","documentation":"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.","triggerScenarios":"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`.","commonSituations":"Endpoints assembled programmatically where the host variable was empty, misconfigured environment variables, or default-constructed request URIs passed to the TLS connector.","solutions":["Ensure the request URI includes a host (e.g. `wss://stream.example.com/ws`).","Validate the endpoint string is non-empty and contains a host before building the request.","If using an IP, note IPv6 must be provided (brackets are stripped automatically); IPv4 literals are fine."],"exampleFix":"// before\nlet uri = \"wss:///stream\"; // no host\n// after\nlet uri = \"wss://stream.example.com/stream\";","handlingStrategy":"validation","validationCode":"fn uri_has_host(req: &Request) -> bool {\n    req.uri().host().map(|h| !h.is_empty()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"if !uri_has_host(&request) {\n    return Err(\"endpoint must include a host, e.g. wss://host/path\".into());\n}\nlet stream = tcp_tls(request).await?;","preventionTips":["Always build request URIs from validated endpoint config containing scheme+host+path.","Check host presence at config load time, before any connect attempt.","Use full connection URLs from venue docs rather than assembled fragments."],"tags":["tls","url","rust","sni"],"backgroundTag":"invalid-url","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}