{"record":{"id":"9dee9677f1c596c0","repo":"Hmbown/CodeWhale","slug":"api-key-not-found-run-codewhale-auth-set","errorCode":null,"errorMessage":"{} API key not found.{} Run 'codewhale auth set --provider {}', set {}, or add [{}] api_key in ~/.codewhale/config.toml.","messagePattern":"(.+?) API key not found\\.(.+?) Run 'codewhale auth set --provider (.+?)', set (.+?), or add \\[(.+?)\\] api_key in ~/\\.codewhale/config\\.toml\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":6710,"sourceCode":"                            .unwrap_or(KIMI_CODE_MEMBERSHIP_PLAN_CONSOLE_URL),\n                        provider.env_vars_label(),\n                        provider_config_table_name(provider)?\n                    );\n                }\n                anyhow::bail!(\n                    \"Moonshot/Kimi API key not found. Get a key: {}. Run 'codewhale auth set --provider moonshot', \\\n                     set {}, or add [{}] api_key. \\\n                     For a Kimi Code plan key, set [providers.moonshot] base_url = \\\n                     \\\"https://api.kimi.com/coding/v1\\\" and model = \\\"kimi-for-coding\\\".\",\n                    credential_help\n                        .credential_url\n                        .unwrap_or(\"https://platform.kimi.ai/console/api-keys\"),\n                    provider.env_vars_label(),\n                    provider_config_table_name(provider)?\n                );\n            }\n            ApiProvider::Anthropic | ApiProvider::Openmodel => {\n                anyhow::bail!(\"{}\", missing_provider_api_key_message(provider)?)\n            }\n            ApiProvider::OpencodeZen => {\n                anyhow::bail!(\"{}\", missing_provider_api_key_message(provider)?)\n            }\n            ApiProvider::OpenaiCodex => anyhow::bail!(\"{}\", crate::oauth::missing_auth_message()),\n            ApiProvider::Xai => {\n                // Prefer OAuth guidance when auth_mode requests it or Grok CLI\n                // tokens already exist; otherwise show both API-key and OAuth.\n                if self\n                    .provider_config_for(provider)\n                    .is_some_and(provider_config_uses_xai_oauth)\n                    || crate::xai_oauth::credentials_present(self)\n                {\n                    anyhow::bail!(\"{}\", crate::xai_oauth::missing_auth_message());\n                }\n                anyhow::bail!(\n                    \"xAI API key not found. Get a key: https://console.x.ai/\\n\\\n                     Run 'codewhale auth set --provider xai', set XAI_API_KEY, or add \\","sourceCodeStart":6692,"sourceCodeEnd":6728,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/config.rs#L6692-L6728","documentation":"Anthropic and Openmodel routes share the generic missing-key formatter missing_provider_api_key_message (crates/tui/src/config.rs:12020). The message interpolates the provider display name, an optional 'Get a key: URL.' hint from provider metadata, the provider slug for 'codewhale auth set', the env var label, and the config table name. It fires when the whole credential chain for these providers is empty and no earlier arm (custom endpoint, OAuth) matched.","triggerScenarios":"provider is ApiProvider::Anthropic or ApiProvider::Openmodel, no custom endpoint, and no api_key in config/auth store/env for the route. The dedicated match arm calls missing_provider_api_key_message(provider)? and bails with the formatted string.","commonSituations":"New machine without ANTHROPIC_API_KEY; the key living only in a CI secret while testing locally; switching from another provider and forgetting the Anthropic credential; logout having cleared stored keys.","solutions":["Run 'codewhale auth set --provider anthropic' (or the Openmodel slug shown in the error)","Export the env var named by env_vars_label (e.g. ANTHROPIC_API_KEY for the route)","Add api_key under the table named in the error ([providers.anthropic] / [providers.openmodel]) in ~/.codewhale/config.toml"],"exampleFix":"# before\n[providers.anthropic]\nmodel = \"claude-...\"\n\n# after\n[providers.anthropic]\nmodel = \"claude-...\"\napi_key = \"sk-ant-...\"","handlingStrategy":"try-catch","validationCode":"if matches!(provider, ApiProvider::Anthropic | ApiProvider::Openmodel) {\n    let present = std::env::var(provider_env_var(provider))\n        .is_ok_and(|v| !v.trim().is_empty())\n        || route_table(provider).api_key.is_some()\n        || auth_store_has(provider);\n    if !present {\n        eprintln!(\"missing {} key; run codewhale auth set --provider {}\", provider.display_name(), provider.as_str());\n    }\n}","typeGuard":null,"tryCatchPattern":"match config.deepseek_api_key() {\n    Err(e) if e.to_string().contains(\"API key not found\")\n        && matches!(provider, ApiProvider::Anthropic | ApiProvider::Openmodel) =>\n    {\n        // the message already lists auth set / env var / config table; prompt and retry\n    }\n    other => other?,\n}","preventionTips":["Run 'codewhale auth set --provider <slug>' during environment provisioning, before first launch","Use the env_vars_label from provider metadata rather than guessing ANTHROPIC_API_KEY-style names","After 'auth logout', expect stored keys to be gone and re-provision before restarting"],"tags":["anthropic","openmodel","credentials","auth"],"backgroundTag":"missing-api-key","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}