Hmbown/CodeWhale · error · anyhow::Error

invalid boolean '{raw}'

Error message

invalid boolean '{raw}'

What it means

Thrown by codewhale-config's parse_bool when a string value for a boolean config field (e.g. insecure_skip_tls_verify, telemetry) does not match any accepted token. Accepted values are exactly 1/true/yes/on/enabled and 0/false/no/off/disabled, matched case-insensitively after trimming surrounding whitespace. Anything else aborts parsing instead of guessing a default, so a typo fails loudly at load time.

Source

Thrown at crates/config/src/lib.rs:6450

    }
    std::fs::copy(&legacy, &primary)
        .context("failed to migrate config from deepseek to codewhale home")?;
    tracing::info!(
        "Migrated config from {} to {}",
        legacy.display(),
        primary.display()
    );
    Ok(Some(ConfigMigration {
        legacy_path: legacy,
        primary_path: primary,
    }))
}

fn parse_bool(raw: &str) -> Result<bool> {
    match raw.trim().to_ascii_lowercase().as_str() {
        "1" | "true" | "yes" | "on" | "enabled" => Ok(true),
        "0" | "false" | "no" | "off" | "disabled" => Ok(false),
        _ => bail!("invalid boolean '{raw}'"),
    }
}

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

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Change the value to one of the ten accepted tokens: 1, true, yes, on, enabled (truthy) or 0, false, no, off, disabled (falsy) — case and surrounding whitespace do not matter
  2. Replace shorthand abbreviations (y, t, f, n, enable) with full tokens (yes, true, no, false, enabled)
  3. Check the field named in the surrounding error context for stray characters: shell quotes kept inside the value, a duplicated value, or a trailing unit/comment

Example fix

# before
insecure_skip_tls_verify = "y"

# after
insecure_skip_tls_verify = "yes"
Defensive patterns

Strategy: validation

Validate before calling

fn parses_as_bool(raw: &str) -> bool {
    matches!(
        raw.trim().to_ascii_lowercase().as_str(),
        "1" | "true" | "yes" | "on" | "enabled"
        | "0" | "false" | "no" | "off" | "disabled"
    )
}

assert!(parses_as_bool(&raw), "boolean override must be one of 1/true/yes/on/enabled or 0/false/no/off/disabled");

Type guard

fn is_valid_codewhale_bool(raw: &str) -> bool {
    matches!(
        raw.trim().to_ascii_lowercase().as_str(),
        "1" | "true" | "yes" | "on" | "enabled"
        | "0" | "false" | "no" | "off" | "disabled"
    )
}

Try / catch

match parse_bool(&raw) {
    Ok(v) => v,
    Err(err) if err.to_string().starts_with("invalid boolean") => {
        // surface which field/value, offer the accepted token list
        return Err(err.context(format!("field {field:?}: use 1/true/yes/on/enabled or 0/false/no/off/disabled")));
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Any boolean override that goes through string parsing: insecure_skip_tls_verify = "maybe", telemetry = "y", or a provider-field override with "enable". Surrounding spaces and any casing (TRUE, Yes) are fine because the value is trimmed and lowercased, but abbreviations like y/t/f/n and words like enable/disable are not in the accepted set.

Common situations: Scripts ported from tools that accept y/n or t/f; CI variables copying shorthand booleans; copy-pasted values that keep a stray quote or append a second token ("true 1"); expectation that YAML-style yes/no covers all abbreviations.

Related errors


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