{"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":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":6404,"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":6386,"sourceCodeEnd":6422,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/config.rs#L6386-L6422","documentation":"For ApiProvider::Anthropic and Openmodel, the missing-key branch delegates to missing_provider_api_key_message() (crates/tui/src/config.rs:11627), which formats '{display_name} API key not found. Get a key: {url}. Run codewhale auth set --provider {id}, set {env_vars}, or add [{table}] api_key in ~/.codewhale/config.toml.' Every placeholder is provider-derived, so the guidance always names the right command, env vars, and TOML table.","triggerScenarios":"provider = anthropic (or openmodel) with no secret-store entry, no provider env var, and no api_key in the provider's config table.","commonSituations":"Fresh setups; ANTHROPIC_API_KEY unset in non-interactive shells (zshrc vs zshenv); keys wiped by `auth logout` / --logout (#343).","solutions":["Run codewhale auth set --provider <provider>.","Or export the provider's env var(s) exactly as named in the message.","Or add api_key under the provider's [providers.<table>] in ~/.codewhale/config.toml.","Get a key from the credential URL included in the message."],"exampleFix":"# before\nprovider = \"anthropic\"\n# no credentials\n\n# after (terminal)\n# codewhale auth set --provider anthropic\n# or: export ANTHROPIC_API_KEY=sk-ant-...","handlingStrategy":"validation","validationCode":"fn provider_key_present(cfg: &Config, provider: ApiProvider) -> bool {\n    provider.env_vars().iter().any(|v| env_nonempty(v)) // e.g. ANTHROPIC_API_KEY\n        || cfg.provider_config_for(provider)\n            .and_then(|pc| pc.api_key)\n            .is_some_and(|k| !k.trim().is_empty())\n        || secret_store_has(provider)\n}\n\nanyhow::ensure!(provider_key_present(&config, ApiProvider::Anthropic), \"auth required\");","typeGuard":"fn provider_credentials_configed(cfg: &Config, provider: ApiProvider) -> bool {\n    provider_key_present(cfg, provider)\n}","tryCatchPattern":"match config.deepseek_api_key() {\n    Err(e) if e.to_string().ends_with(\"API key not found.\") || e.to_string().contains(\"Run 'codewhale auth set --provider\") => {\n        run_auth_set(provider)?; // interactive: codewhale auth set --provider <id>\n        config.deepseek_api_key()\n    }\n    other => other,\n}","preventionTips":["Run codewhale auth set --provider <id> during machine setup, not at request time.","Check env vars exist in the exact launching context (service manager, CI, cron).","After logout/--logout, expect stored keys to be gone and re-authenticate."],"tags":["rust","anthropic","api-key","authentication","config"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}