{"record":{"id":"33aea36622f54acd","repo":"Hmbown/CodeWhale","slug":"xai-api-key-not-found-get-a-key-https-console","errorCode":null,"errorMessage":"xAI API key not found. Get a key: https://console.x.ai/\nRun 'codewhale auth set --provider xai', set XAI_API_KEY, or add [providers.xai] api_key.\nOAuth alternative: run `codewhale auth xai-device` for Codewhale-owned storage and set [providers.xai] auth_mode = \"oauth\".","messagePattern":"xAI API key not found\\. Get a key: https://console\\.x\\.ai/\nRun 'codewhale auth set --provider xai', set XAI_API_KEY, or add \\[providers\\.xai\\] api_key\\.\nOAuth alternative: run `codewhale auth xai-device` for Codewhale-owned storage and set \\[providers\\.xai\\] auth_mode = \"oauth\"\\.","errorType":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":6420,"sourceCode":"            }\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 \\\n                     [providers.xai] api_key.\\n\\\n                     OAuth alternative: run `codewhale auth xai-device` for \\\n                     Codewhale-owned storage and set [providers.xai] auth_mode = \\\"oauth\\\".\"\n                );\n            }\n            // Self-hosted deployments commonly run without auth on localhost.\n            // Return an empty key and let the client omit the Authorization header.\n            ApiProvider::Sglang | ApiProvider::Vllm => Ok(String::new()),\n            ApiProvider::Ollama\n                if provider_route_is_keyless_self_hosted(provider, &self.deepseek_base_url()) =>\n            {\n                Ok(String::new())\n            }\n            ApiProvider::Ollama => {\n                let help = credential_help_for_provider_route(provider, &self.deepseek_base_url());\n                anyhow::bail!(","sourceCodeStart":6402,"sourceCodeEnd":6438,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/config.rs#L6402-L6438","documentation":"The default xAI branch: auth_mode is not oauth and no Grok CLI tokens are on disk, so plain API-key guidance is shown — get a key from console.x.ai, persist it via auth set / XAI_API_KEY / [providers.xai] api_key, with the OAuth alternative (codewhale auth xai-device plus auth_mode = \"oauth\") as the last option.","triggerScenarios":"provider = xai with no secret-store key, no XAI_API_KEY, no [providers.xai] api_key, and no OAuth path selected.","commonSituations":"First-time xAI/Grok usage; keys wiped by logout; env var missing in non-interactive shells.","solutions":["Run codewhale auth set --provider xai.","Or export XAI_API_KEY in the launching shell.","Or add api_key under [providers.xai] in ~/.codewhale/config.toml.","For OAuth instead: codewhale auth xai-device and set [providers.xai] auth_mode = \"oauth\"."],"exampleFix":"# before\nprovider = \"xai\"\n# no credentials\n\n# after (terminal)\n# codewhale auth set --provider xai\n# or: export XAI_API_KEY=xai-...","handlingStrategy":"validation","validationCode":"fn xai_key_present(cfg: &Config) -> bool {\n    env_nonempty(\"XAI_API_KEY\")\n        || cfg.provider_config_for(ApiProvider::Xai)\n            .and_then(|pc| pc.api_key)\n            .is_some_and(|k| !k.trim().is_empty())\n        || secret_store_has(ApiProvider::Xai)\n}\n\nanyhow::ensure!(xai_key_present(&config), \"configure xAI auth (key or OAuth) first\");","typeGuard":"fn xai_credentials_configured(cfg: &Config) -> bool {\n    xai_key_present(cfg) || xai_oauth_ready(cfg)\n}","tryCatchPattern":"match config.deepseek_api_key() {\n    Err(e) if e.to_string().starts_with(\"xAI API key not found\") => {\n        run_auth_set(ApiProvider::Xai)?; // or guide to codewhale auth xai-device\n        config.deepseek_api_key()\n    }\n    other => other,\n}","preventionTips":["Persist the key via codewhale auth set --provider xai or [providers.xai] api_key.","If you prefer OAuth, complete the device flow and set auth_mode = \"oauth\" so the OAuth guidance branch is used."],"tags":["rust","xai","api-key","authentication","config"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}