openai/codex · error

MCP HTTP headers helper returned an invalid header name

Error message

MCP HTTP headers helper returned an invalid header name

What it means

Each key in the helper's JSON must be a valid HTTP header name per HeaderName::from_bytes: ASCII token characters — letters, digits, and !#$%&'*+-.^_`|~ — with no spaces, colons, CR/LF, or non-ASCII bytes. Output like a full header line ("Authorization: Bearer x") used as the key, or a name with a space, fails here before the reserved-header check.

Source

Thrown at codex-rs/rmcp-client/src/http_headers.rs:366

fn parse_helper_output(stdout: Vec<u8>) -> Result<HeaderMap> {
    let stdout = String::from_utf8(stdout)
        .map_err(|_| anyhow!("MCP HTTP headers helper wrote non-UTF-8 data"))?;
    let mut deserializer = serde_json::Deserializer::from_str(stdout.trim());
    let headers = RawHeaderEntries::deserialize(&mut deserializer)
        .and_then(|headers| {
            deserializer.end()?;
            Ok(headers)
        })
        .map_err(|_| anyhow!("MCP HTTP headers helper must output a JSON object of strings"))?;
    if headers.has_exact_duplicate {
        return Err(anyhow!(
            "MCP HTTP headers helper returned duplicate header names"
        ));
    }
    let mut parsed = HeaderMap::with_capacity(headers.entries.len());
    for (name, value) in headers.entries {
        let name = HeaderName::from_bytes(name.as_bytes())
            .map_err(|_| anyhow!("MCP HTTP headers helper returned an invalid header name"))?;
        // Helper values replace same-name configured headers; bearer/OAuth owns Authorization.
        // Google IAP uses Proxy-Authorization alongside application Authorization. For HTTPS MCP
        // URLs it is sent through the forward-proxy tunnel to IAP, not used as CONNECT auth.
        if matches!(
            name.as_str(),
            "accept"
                | "authorization"
                | "connection"
                | "content-encoding"
                | "content-length"
                | "content-type"
                | "host"
                | "keep-alive"
                | "last-event-id"
                | "mcp-protocol-version"
                | "mcp-session-id"
                | "origin"
                | "proxy-connection"

View on GitHub (pinned to 339751715c)

Solutions

  1. Emit only the header name as the key — no colon, no value, no trailing space
  2. Restrict names to letters, digits, and hyphens (safest subset of token chars)
  3. Validate with a token regex before printing: ^[!#$%&'*+.^_`|~0-9A-Za-z]+$
  4. If the name came from a parsed header line, split on the first colon and trim

Example fix

# before
{"Authorization: Bearer x": "unused"}

# after
{"X-Api-Key": "..."}
Defensive patterns

Strategy: validation

Validate before calling

# Every key must be a valid HTTP token name
cd "$MCP_CWD" && env -i PATH=/usr/bin:/bin sh -c "$HTTP_HEADERS_HELPER" \
  | jq -r 'keys[]' | grep -Ev "^[!#\$%&'*+.^_`|~0-9A-Za-z]+$" \
  && echo invalid-header-name || echo names-ok

Type guard

fn is_valid_header_name(name: &str) -> bool {
    !name.is_empty()
        && name.bytes().all(|b| b.is_ascii_alphanumeric() || b![!#$%&'*+.^_`|~].contains(&b))
}

Prevention

When it happens

Trigger: Helper emitting full 'Name: value' lines wrapped as keys, header names containing spaces or non-token characters, trailing colons, or non-ASCII names (e.g. accented organization names).

Common situations: Scripts that echo raw HTTP header lines and naively wrap them in JSON; copy-pasted names with trailing colons; Unicode names from internal systems; keys built by string concatenation without token validation.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/474a567d7efc1225. Report an issue: GitHub.