Hmbown/CodeWhale · error

unknown scope ` `; Codewhale API keys accept only

Error message

unknown scope `{}`; Codewhale API keys accept only {}

What it means

Scope parsing for Codewhale API keys accepts only the fixed SCOPES allowlist. Each scope string is trimmed and checked against the list; anything else bails listing the accepted scopes. Codewhale keys deliberately support a small closed scope set, so unknown values are rejected client-side.

Solutions

  1. Run the command with no scopes or read the error's list of accepted scopes
  2. Use only exact strings from SCOPES (check `codewhale account api-keys create --help` for the list)
  3. Fix typos and casing to match the allowlist exactly
  4. Remove any scope imported from another product's naming scheme

Example fix

// before
codewhale account api-keys create --scope admin --scope inference
// after
codewhale account api-keys create --scope inference   # use an exact name from SCOPES
Defensive patterns

Strategy: validation

Validate before calling

// only allowlist scopes accepted by the CLI
const SCOPES: [&str; 2] = ["inference", "sessions"]; // check --help for the exact list
fn scopes_ok(requested: &[&str]) -> bool {
    requested.iter().all(|s| SCOPES.contains(&s.trim()))
}

Prevention

When it happens

Trigger: Passing a scope argument to an api-keys create/update command that is not in SCOPES — misspelled names, plural/singular mismatches, invented scopes like "admin" or "write:all", or scopes from another product's convention (crates/cli/src/cloud/machine.rs:830).

Common situations: Copying scope names from GitHub/OAuth docs, typos like "read:sesssions", assuming wildcard scopes exist, or case differences since the check is exact-match after trim.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/86d2687f23022ac4. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/cloud/machine.rs:830

}

/// Normalize `--scope` into the closed set.
///
/// An omitted `--scope` means every scope, and is sent explicitly rather than
/// left to a server default: a key minted by this CLI should carry exactly the
/// scopes the CLI's own help promised, whatever the control plane's default is
/// this week.
pub(crate) fn validate_scopes(scopes: &[String]) -> Result<Option<Vec<String>>> {
    if scopes.is_empty() {
        return Ok(Some(
            SCOPES.iter().map(|scope| (*scope).to_string()).collect(),
        ));
    }
    let mut normalized = Vec::new();
    for scope in scopes {
        let scope = scope.trim();
        if !SCOPES.contains(&scope) {
            bail!(
                "unknown scope `{}`; Codewhale API keys accept only {}",
                printable(scope),
                SCOPES.join(", ")
            );
        }
        if !normalized.iter().any(|existing| existing == scope) {
            normalized.push(scope.to_string());
        }
    }
    Ok(Some(normalized))
}

/// The 24-hex key id, checked locally.
///
/// This is a paste check, not an existence check: the server answers 404
/// identically for a malformed id, an unknown id, and another account's id, so
/// nothing here can or should try to distinguish them.
pub(crate) fn validate_key_id(id: &str) -> Result<&str> {

View on GitHub (pinned to 73e0f67d83)