{"record":{"id":"7ace602afad4e3fd","repo":"Hmbown/CodeWhale","slug":"api-key-name-must-be-1-max-key-name-chars-characters-start","errorCode":null,"errorMessage":"API key name must be 1-{MAX_KEY_NAME_CHARS} characters, start with a letter or digit, and contain only letters, digits, spaces, and `. _ : @ / -`.","messagePattern":"API key name must be 1-(.+?) characters, start with a letter or digit, and contain only letters, digits, spaces, and `\\. _ : @ / -`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/cloud/machine.rs","lineNumber":793,"sourceCode":"    #[arg(long = \"expires-in-days\", value_parser = clap::value_parser!(u32).range(1..=i64::from(MAX_EXPIRY_DAYS)))]\n    expires_in_days: Option<u32>,\n    /// Repeatable. Omit for all of `account:read`, `agent:run`, `models:infer`.\n    #[arg(long = \"scope\", value_name = \"SCOPE\")]\n    scopes: Vec<String>,\n    /// Also save the new secret as this machine's local `codewhale` provider\n    /// credential, so the CLI can immediately use Codewhale API models.\n    ///\n    /// The key never leaves this machine: it goes to the same secret store\n    /// `codewhale auth` writes, and nothing is uploaded anywhere.\n    #[arg(long = \"use\", default_value_t = false)]\n    use_locally: bool,\n}\n\n/// `/^[A-Za-z0-9][A-Za-z0-9 ._:@\\/-]{0,63}$/`, checked locally so a bad name\n/// costs a message instead of a round trip.\npub(crate) fn validate_key_name(name: &str) -> Result<&str> {\n    let invalid = || {\n        anyhow!(\n            \"API key name must be 1-{MAX_KEY_NAME_CHARS} characters, start with a letter or \\\ndigit, and contain only letters, digits, spaces, and `. _ : @ / -`.\"\n        )\n    };\n    let mut characters = name.chars();\n    let Some(first) = characters.next() else {\n        return Err(invalid());\n    };\n    if !first.is_ascii_alphanumeric() || name.chars().count() > MAX_KEY_NAME_CHARS {\n        return Err(invalid());\n    }\n    if characters.any(|character| {\n        !character.is_ascii_alphanumeric()\n            && !matches!(character, ' ' | '.' | '_' | ':' | '@' | '/' | '-')\n    }) {\n        return Err(invalid());\n    }\n    Ok(name)","sourceCodeStart":775,"sourceCodeEnd":811,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/cloud/machine.rs#L775-L811","documentation":"Local pre-flight validation of a user-supplied API key name, mirroring the server regex `/^[A-Za-z0-9][A-Za-z0-9 ._:@\\/-]{0,63}$/`. It fails fast client-side so an invalid name costs a message instead of a network round trip.","triggerScenarios":"Creating or renaming an API key with a name that is empty, longer than MAX_KEY_NAME_CHARS (64), starts with a non-alphanumeric character, or contains characters outside letters, digits, spaces, and `. _ : @ / -`.","commonSituations":"Names with quotes, emoji, `#`, or leading `-`/`_`; scripted names with shell-expanded odd characters; names over 64 chars generated from hostnames or timestamps.","solutions":["Use a name matching the regex: start with a letter/digit, ≤64 chars, only `A-Za-z0-9 . _ : @ / -` and spaces.","Trim whitespace and strip shell-mangled characters from scripts.","Shorten auto-generated names to fit the 64-char limit."],"exampleFix":"// before\ncodewhale account api-keys create --name \"ci key (prod)!\"\n// after\ncodewhale account api-keys create --name \"ci key prod-01\"","handlingStrategy":"validation","validationCode":"fn valid_key_name(name: &str) -> bool {\n    let n = name.chars().count();\n    n >= 1 && n <= 64\n        && name.chars().next().map_or(false, |c| c.is_ascii_alphanumeric())\n        && name.chars().all(|c| c.is_ascii_alphanumeric() || \" ._:@/-\".contains(c))\n}","typeGuard":"fn valid_key_name(name: &str) -> bool {\n    let n = name.chars().count();\n    n >= 1 && n <= 64\n        && name.chars().next().map_or(false, |c| c.is_ascii_alphanumeric())\n        && name.chars().all(|c| c.is_ascii_alphanumeric() || \" ._:@/-\".contains(c))\n}","tryCatchPattern":null,"preventionTips":["Enforce the regex `/^[A-Za-z0-9][A-Za-z0-9 ._:@\\/-]{0,63}$/` in scripts that generate names.","Sanitize shell-expanded names; quote arguments.","Cap generated names at 64 characters."],"tags":["validation","cli","api-key"],"backgroundTag":"invalid-argument-format","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}