Hmbown/CodeWhale · error · anyhow::Error

header name cannot be empty

Error message

header name cannot be empty

What it means

After parse_http_headers splits a pair on '=', the name side is trimmed and checked; an empty name bails with 'header name cannot be empty'. This catches pairs like '=value' or ' =value' where everything before '=' is blank. Note the value side is treated differently: an empty value causes the pair to be silently skipped, not an error.

Source

Thrown at crates/tui/src/config.rs:9963

        return trimmed.trim_end_matches("/v1").to_string();
    }
    trimmed.to_string()
}

fn parse_http_headers(raw: &str) -> Result<HashMap<String, String>> {
    let mut headers = HashMap::new();
    for pair in raw.trim().split(',') {
        let pair = pair.trim();
        if pair.is_empty() {
            continue;
        }
        let Some((name, value)) = pair.split_once('=') else {
            anyhow::bail!("invalid header pair '{pair}', expected name=value");
        };
        let name = name.trim();
        let value = value.trim();
        if name.is_empty() {
            anyhow::bail!("header name cannot be empty");
        }
        if value.is_empty() {
            continue;
        }
        headers.insert(name.to_string(), value.to_string());
    }
    Ok(headers)
}

fn apply_profile(config: ConfigFile, profile: Option<&str>) -> Result<Config> {
    if let Some(profile_name) = profile {
        let profiles = config.profiles.as_ref();
        match profiles.and_then(|profiles| profiles.get(profile_name)) {
            Some(override_cfg) => Ok(merge_config(config.base, override_cfg.clone())),
            None => {
                let available = profiles
                    .map(|profiles| {
                        let mut keys = profiles.keys().cloned().collect::<Vec<_>>();

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Give every pair a non-empty name: 'X-App=abc' not '=abc'
  2. Inspect for stray ',=' sequences when building the string dynamically and filter empty names before joining
  3. Prefer the structured config (http_headers map) over the raw string when names come from user input

Example fix

# before
$ codewhale --http-headers "X-App=1,=2"
# error: header name cannot be empty

# after
$ codewhale --http-headers "X-App=1,X-Env=2"
Defensive patterns

Strategy: validation

Validate before calling

// Reject empty header names before launch:
fn no_empty_header_names(raw: &str) -> bool {
    raw.trim().split(',').all(|pair| {
        let pair = pair.trim();
        pair.is_empty()
            || pair.split_once('=').is_some_and(|(name, _)| !name.trim().is_empty())
    })
}
assert!(no_empty_header_names(&raw), "header pairs need a non-empty name");

Type guard

fn header_pair_has_name(pair: &str) -> bool {
    pair.trim()
        .split_once('=')
        .is_some_and(|(name, _)| !name.trim().is_empty())
}

Try / catch

match parse_http_headers(&raw) {
    Err(e) if e.to_string() == "header name cannot be empty" => {
        // point at ',=' artifacts or missing names; strip empty-name segments and retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: Passing a header string containing a pair with no name, e.g. '--http-headers "=abc123"' or a stray '=' after a comma ('"a=1,=2"'). The name.trim().is_empty() check fires after the split_once succeeds.

Common situations: A trailing comma followed by '=' from sloppy concatenation in scripts; building the header string programmatically and emitting the name field as an empty string; copy/paste artifacts where the header name line was deleted but the value remained.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/85d417e326b62f1b. Report an issue: GitHub.