nautechsystems/nautilus_trader · error · TransportError

Invalid WebSocket reconnect header name: {e}

Error message

Invalid WebSocket reconnect header name: {e}

What it means

The reconnect header update API validates the header name with HeaderName::from_bytes (from the http crate). Names must be valid HTTP header names (token characters only, no spaces or non-ASCII). If parsing fails, this InvalidInput TransportError is returned and the header is not updated. This is a caller input-validation error, not a network condition.

Source

Thrown at crates/network/src/websocket/client.rs:2276

pub struct ReconnectHeaders {
    inner: Arc<RwLock<Vec<(String, String)>>>,
}

impl ReconnectHeaders {
    fn new(headers: Vec<(String, String)>) -> Self {
        Self {
            inner: Arc::new(RwLock::new(headers)),
        }
    }

    /// Replaces a header used by future automatic reconnect attempts.
    ///
    /// # Errors
    ///
    /// Returns an error if the header name or value is invalid.
    pub fn update(&self, name: &str, value: &str) -> Result<(), TransportError> {
        let name = HeaderName::from_bytes(name.as_bytes()).map_err(|e| {
            TransportError::Io(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!("Invalid WebSocket reconnect header name: {e}"),
            ))
        })?;
        HeaderValue::from_str(value).map_err(|e| {
            TransportError::Io(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!("Invalid WebSocket reconnect header value: {e}"),
            ))
        })?;

        let name = name.as_str();
        let mut headers = self.inner.write();
        headers.retain(|(existing, _)| !existing.eq_ignore_ascii_case(name));
        headers.push((name.to_string(), value.to_string()));
        Ok(())
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Correct the header name to a valid HTTP token (letters, digits, '-', '_', '.', alphanumerics only)
  2. Trim whitespace and validate names from config/env before calling update
  3. Use a constant/known-good header name instead of a dynamically built one where possible

Example fix

// before
headers.update("X API Key", key)?; // invalid: space in name
// after
headers.update("X-Api-Key", key)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_header_name(name: &str) -> bool {
    !name.is_empty()
        && name.bytes().all(|b| b.is_ascii_alphanumeric() || b"-_.".contains(&b))
}

Try / catch

match headers.update(name, value) {
    Err(e) if e.to_string().contains("header name") => return Err(InvalidConfig(format!("bad header name {name:?}"))),
    r => r?,
}

Prevention

When it happens

Trigger: Calling WebSocketReconnectHeaders::update (or the equivalent client API) with a name containing invalid characters, whitespace, colon, or empty string, e.g. update("X Custom Header", "v").

Common situations: Building header names dynamically from config or environment strings with typos/spaces; concatenating name parts with separators; copying header names with trailing whitespace from docs.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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