Hmbown/CodeWhale · error · anyhow::Error
invalid header pair '{pair}', expected name=value
Error message
invalid header pair '{pair}', expected name=value What it means
parse_http_headers splits a comma-separated raw string on '=' to build the extra-headers map sent to model API requests. A non-empty pair that contains no '=' at all (split_once('=') returns None) bails with 'invalid header pair \'{pair}\', expected name=value'. Empty segments between commas are skipped, so only genuinely malformed pairs trigger it.
Source
Thrown at crates/tui/src/config.rs:9958
let deepseek_domains = ["api.deepseek.com", "api.deepseeki.com"];
if deepseek_domains
.iter()
.any(|domain| trimmed.contains(domain))
{
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)) {View on GitHub (pinned to 0c42157ee5)
Solutions
- Convert each header to name=value form: 'Authorization=Bearer tok' instead of 'Authorization: Bearer tok'
- Ensure every comma-separated segment either is empty or contains exactly a name=value pair
- For values containing commas, check whether the surface accepts repeated flags or a config table instead of one raw string
Example fix
# before $ codewhale --http-headers "X-Trace-Id: abc123" # error: invalid header pair 'X-Trace-Id: abc123', expected name=value # after $ codewhale --http-headers "X-Trace-Id=abc123"
Defensive patterns
Strategy: validation
Validate before calling
// Validate a raw header string with the same rule before passing it in:
fn http_headers_string_ok(raw: &str) -> bool {
raw.trim().split(',').all(|pair| {
let pair = pair.trim();
pair.is_empty() || pair.split_once('=').is_some()
})
}
assert!(http_headers_string_ok(&raw), "every header pair must be name=value"); Type guard
fn is_valid_header_pair(pair: &str) -> bool {
let pair = pair.trim();
pair.is_empty() || pair.split_once('=').is_some_and(|(n, _)| !n.trim().is_empty())
} Try / catch
match parse_http_headers(&raw) {
Err(e) if e.to_string().starts_with("invalid header pair") => {
// show the offending pair, hint 'name=value not name: value', and re-prompt
}
other => other?,
} Prevention
- Translate curl-style 'Name: value' headers to 'Name=value' before passing them
- When building the string programmatically, filter out segments without '=' before joining with commas
- Prefer the structured http_headers config map over the raw string when input comes from users
When it happens
Trigger: Passing --http-headers (or the equivalent config/setting) with a segment like 'Authorization: Bearer tok' (colon syntax), a bare token such as 'x-trace', or a value containing spaces that split off a fragment without '='.
Common situations: Copying a curl-style '-H "Name: value"' header into Codewhale's name=value syntax; trailing punctuation after a pair; values containing '=' are fine but values with commas force a split that can orphan text.
Related errors
- header name cannot be empty
- unrecognised character {ch:?} in duration {s:?}
- The Codewhale service returned an account without an ID
- invalid value '{provider}' for '--provider <PROVIDER>': expe
- --worktree-repo and --branch must be provided together
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/f95f04382edf268e.
Report an issue: GitHub.