zeroclaw-labs/zeroclaw · error · anyhow::Error

URL cannot contain whitespace

Error message

URL cannot contain whitespace

What it means

Thrown by HttpRequestTool::validate_url_policy (crates/zeroclaw-tools/src/http_request.rs:127) when the URL, after leading/trailing trimming, still contains any whitespace character (space, tab, newline) anywhere in it. The http_request tool rejects such URLs before scheme or allowlist checks because unencoded whitespace is invalid in an HTTP request target and can be used to smuggle or corrupt headers. It is a fail-closed input-validation error, not a network error.

Source

Thrown at crates/zeroclaw-tools/src/http_request.rs:127

            config_path: Some(config_path),
            secrets_encrypt,
        })
    }

    #[cfg(test)]
    fn validate_url(&self, raw_url: &str) -> anyhow::Result<String> {
        Ok(self.validate_url_policy(raw_url)?.url)
    }

    fn validate_url_policy(&self, raw_url: &str) -> anyhow::Result<HttpRequestUrlPolicy> {
        let url = raw_url.trim();

        if url.is_empty() {
            anyhow::bail!("URL cannot be empty");
        }

        if url.chars().any(char::is_whitespace) {
            anyhow::bail!("URL cannot contain whitespace");
        }

        if !url.starts_with("http://") && !url.starts_with("https://") {
            anyhow::bail!("Only http:// and https:// URLs are allowed");
        }

        if self.allowed_domains.is_empty() {
            anyhow::bail!(
                "HTTP request tool is enabled but no allowed_domains are configured. Add [http_request].allowed_domains in config.toml"
            );
        }

        let host = extract_host(url)?;
        if let Ok(ip) = host.parse::<IpAddr>() {
            if domain_guard::is_known_cloud_metadata_endpoint(ip) {
                anyhow::bail!("Blocked cloud metadata host: {host}");
            }
            if domain_guard::is_cloud_metadata_ip(ip) {

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Percent-encode every space and control character in the path/query before calling the tool (space -> %20, tab -> %09, newline -> %0A).
  2. Trim the URL and assert it has no interior whitespace before invoking http_request.
  3. Build URLs with a URL encoder (e.g. url::Url with query_pairs_mut, or urlencoding::encode) instead of raw string concatenation.

Example fix

// before
let args = json!({"url": "https://example.com/hello world"});
tool.execute(args).await?; // -> URL cannot contain whitespace

// after
let args = json!({"url": "https://example.com/hello%20world"});
tool.execute(args).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn url_is_clean(url: &str) -> bool {
    let t = url.trim();
    !t.is_empty() && !t.chars().any(char::is_whitespace)
}

Type guard

fn has_interior_whitespace(url: &str) -> bool {
    url.trim().chars().any(char::is_whitespace)
}

Try / catch

let result = tool.execute(args).await?;
if let Some(err) = &result.error {
    if err.contains("URL cannot contain whitespace") {
        // percent-encode the URL and retry once with sanitized input
    }
}

Prevention

When it happens

Trigger: Calling tool.execute with args.url = "https://example.com/hello world" (unencoded space in the path); a URL pasted from a terminal that contains a tab or a line-wrap newline; building the URL by string concatenation where one variable carries interior whitespace. Leading/trailing whitespace alone does NOT trigger it because the URL is trimmed first; only interior whitespace does.

Common situations: LLM/agent-generated URLs containing natural-language fragments; URLs copied from documentation that wrapped across lines; query strings assembled with raw spaces instead of percent-encoding; templating code that interpolates unvalidated user input into the path or query.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/760a41b45bbacce4. Report an issue: GitHub.