affaan-m/ECC · warning · anyhow::Error

Missing HTTP method

Error message

Missing HTTP method

What it means

A sibling parse error in the same HTTP request reader: the request line existed, but splitting it on whitespace produced no method token, so `request_parts.next()` returned `None`. Since every HTTP request line must begin with a method (GET, POST, ...), the parser rejects the input with this message.

Solutions

  1. Ensure the request line follows `METHOD SP PATH SP HTTP/x.x` format with real spaces.
  2. Check the client isn't sending binary/TLS data to this plain-HTTP listener.
  3. Reproduce with curl to confirm the server works with standard clients.
  4. If handling a proxy, account for PROXY protocol headers or disable that on the port.

Example fix

// before
$ printf '\r\n/foo HTTP/1.1\r\n\r\n' | nc localhost 8080
error: Missing HTTP method
// after
$ printf 'GET /foo HTTP/1.1\r\nHost: localhost\r\n\r\n' | nc localhost 8080
Defensive patterns

Strategy: try-catch

Try / catch

// Client side: always emit a canonical request line
let request = format!("GET {path} HTTP/1.1\r\nHost: {host}\r\n\r\n");
stream.write_all(request.as_bytes())?;

Prevention

When it happens

Trigger: A request line consisting solely of whitespace/` ` characters that survived the earlier empty-line filter; garbled binary sent where the method should be; a client writing only a path or headers without `METHOD PATH VERSION`.

Common situations: Fuzzing or malformed client traffic hitting the dev server; protocol confusion (e.g. sending PROXY protocol or TLS bytes); hand-crafted socket scripts with wrong formatting; truncated writes that clip the method.

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 affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/06f41e564de95beb. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/main.rs:4219

        if let Some(index) = buffer.windows(4).position(|window| window == b"\r\n\r\n") {
            break index + 4;
        }
        if buffer.len() > 64 * 1024 {
            anyhow::bail!("HTTP request headers too large");
        }
    };

    let header_text = String::from_utf8(buffer[..header_end].to_vec())
        .context("HTTP request headers were not valid UTF-8")?;
    let mut lines = header_text.split("\r\n");
    let request_line = lines
        .next()
        .filter(|line| !line.trim().is_empty())
        .ok_or_else(|| anyhow::anyhow!("Missing HTTP request line"))?;
    let mut request_parts = request_line.split_whitespace();
    let method = request_parts
        .next()
        .ok_or_else(|| anyhow::anyhow!("Missing HTTP method"))?
        .to_string();
    let path = request_parts
        .next()
        .ok_or_else(|| anyhow::anyhow!("Missing HTTP path"))?
        .to_string();

    let mut headers = BTreeMap::new();
    for line in lines {
        if line.is_empty() {
            break;
        }
        if let Some((key, value)) = line.split_once(':') {
            headers.insert(key.trim().to_ascii_lowercase(), value.trim().to_string());
        }
    }

    let content_length = headers
        .get("content-length")

View on GitHub (pinned to 8321021c54)