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

Unsupported HTTP method: {method}. Supported: GET, POST, PUT

Error message

Unsupported HTTP method: {method}. Supported: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS

What it means

Thrown by HttpRequestTool::validate_method (crates/zeroclaw-tools/src/http_request.rs:239) when the method string, after to_uppercase(), is not one of GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS. The tool intentionally exposes only these seven methods; anything else (including empty strings and methods with trailing whitespace) is rejected before the request is built. Lowercase input like "get" is accepted because it is uppercased first.

Source

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

        )?;

        Ok(ValidatedHttpRequestTarget {
            url: policy.url,
            host: policy.host,
            resolved_addrs,
        })
    }

    fn validate_method(&self, method: &str) -> anyhow::Result<reqwest::Method> {
        match method.to_uppercase().as_str() {
            "GET" => Ok(reqwest::Method::GET),
            "POST" => Ok(reqwest::Method::POST),
            "PUT" => Ok(reqwest::Method::PUT),
            "DELETE" => Ok(reqwest::Method::DELETE),
            "PATCH" => Ok(reqwest::Method::PATCH),
            "HEAD" => Ok(reqwest::Method::HEAD),
            "OPTIONS" => Ok(reqwest::Method::OPTIONS),
            _ => anyhow::bail!(
                "Unsupported HTTP method: {method}. Supported: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS"
            ),
        }
    }

    fn parse_headers(&self, headers: &serde_json::Value) -> anyhow::Result<HeaderMap> {
        let mut result = HeaderMap::new();
        if let Some(obj) = headers.as_object() {
            for (key, value) in obj {
                let Some(str_val) = value.as_str() else {
                    anyhow::bail!("Header '{key}' value must be a string, got: {}", value);
                };
                let header_name = HeaderName::from_str(key)
                    .map_err(|e| anyhow::Error::msg(format!("Invalid header name '{key}': {e}")))?;
                let header_value = HeaderValue::from_str(str_val).map_err(|e| {
                    anyhow::Error::msg(format!("Invalid value for header '{key}': {e}"))
                })?;
                result.insert(header_name, header_value);

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Use one of the seven supported methods; for cache purge, switch the API to its POST- or DELETE-based variant if it has one.
  2. Trim the method string before passing it (method.trim()), since interior/trailing whitespace defeats the match.
  3. If you control the server, expose the operation under a supported verb (e.g. POST /cache/purge instead of PURGE /).

Example fix

// before
let args = json!({"url": "https://cdn.example.com/img", "method": "PURGE"});

// after
let args = json!({"url": "https://cdn.example.com/cache/purge", "method": "POST"});
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED: &[&str] = &["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"];
fn method_supported(method: &str) -> bool {
    SUPPORTED.contains(&method.to_uppercase().as_str())
}

Type guard

fn is_supported_method(method: &str) -> bool {
    method.to_uppercase().trim().is_empty() == false
        && SUPPORTED.contains(&method.to_uppercase().trim())
}

Try / catch

let result = tool.execute(args).await?;
if let Some(err) = &result.error {
    if err.contains("Unsupported HTTP method") {
        // fall back to the closest supported verb the API also accepts (often POST)
    }
}

Prevention

When it happens

Trigger: args.method = "TRACE", "CONNECT", or "PURGE" (CDN purge verbs); method = "" (empty string matches nothing); method = "GET " with a trailing space or newline (does not equal "GET" after uppercasing); a WebDAV verb like "PROPFIND".

Common situations: Wrapping CDN or cache-admin APIs that need PURGE; WebDAV integrations; LLM-produced method strings with stray whitespace; forwarding a raw method header from another request verbatim.

Related errors


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