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

Invalid URL: {e}

Error message

Invalid URL: {e}

What it means

parse_socket_url validates a WebSocket/socket URL. If the string contains "://" it is parsed as an http::Uri; a malformed URI raises "Invalid URL: {e}" (InvalidInput io error). Related checks in the same function also reject missing host/port, but this specific error fires when the URL cannot be parsed as a URI at all.

Source

Thrown at crates/network/src/socket/client.rs:284

            reconnect_attempt_count: 0,
            state_sink,
        })
    }

    /// Parses a URL into its socket address and request URL.
    ///
    /// Accepts either:
    /// - Raw socket address: "host:port" → returns ("host:port", "scheme://host:port")
    /// - Full URL: "scheme://host:port/path" → returns ("host:port", original URL)
    ///
    /// # Errors
    ///
    /// Returns an error if the URL is invalid or missing required components.
    fn parse_socket_url(url: &str, mode: Mode) -> Result<(String, String), Error> {
        if url.contains("://") {
            // URL with scheme (e.g., "wss://host:port/path")
            let parsed = url.parse::<http::Uri>().map_err(|e| {
                Error::Io(std::io::Error::new(
                    std::io::ErrorKind::InvalidInput,
                    format!("Invalid URL: {e}"),
                ))
            })?;

            let host = parsed.host().ok_or_else(|| {
                Error::Io(std::io::Error::new(
                    std::io::ErrorKind::InvalidInput,
                    "URL missing host",
                ))
            })?;

            let port = parsed
                .port_u16()
                .unwrap_or_else(|| match parsed.scheme_str() {
                    Some("wss" | "https") => 443,
                    Some("ws" | "http") => 80,
                    _ => match mode {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Validate the URL before constructing the client: it must parse as http::Uri and include scheme, host, and port.
  2. Trim whitespace/quotes and percent-encode special characters in the URL.
  3. Use the correct scheme (ws:// or wss://) with the full authority, e.g. wss://host:port/path.
  4. Check the config source (env var, YAML) for interpolated values that broke the URL.
  5. If credentials are needed, put them in headers/options, not mangled into the URL string.

Example fix

// before
let url = std::env::var("WS_URL")?;           // "wss://host :443" -> Invalid URL
let client = SocketClient::new(url, mode);
// after
let url = std::env::var("WS_URL")?.trim().to_string();
url.parse::<http::Uri>().expect("valid ws url");
let client = SocketClient::new(url, mode);
Defensive patterns

Strategy: validation

Validate before calling

fn valid_socket_url(url: &str) -> bool {
    url.trim().parse::<http::Uri>().map(|u| {
        u.scheme_str().is_some() && u.host().is_some()
    }).unwrap_or(false)
}

Try / catch

let url = config.ws_url.trim();
if !valid_socket_url(url) {
    anyhow::bail!("config ws_url is not a valid URI: {url:?}");
}
let client = SocketClient::new(url.to_string(), mode);

Prevention

When it happens

Trigger: Passing a URL with an invalid scheme or characters (spaces, unencoded non-ASCII, stray brackets) to a network socket client config — e.g. ws_url="wss:/host:port" (single slash), "wss://host :443", or a URL with embedded credentials in the wrong place.

Common situations: Typo'd scheme or missing slash in a config file/env var; copy-pasting a URL with trailing whitespace or quotes; unencoded special characters (spaces, unicode) from templating; mistakenly passing a bare hostname while thinking "://" was present.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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