Hmbown/CodeWhale · error · anyhow::Error
OpenAI Codex OAuth credentials are unavailable. Codewhale c
Error message
OpenAI Codex OAuth credentials are unavailable.
Codewhale checks OPENAI_CODEX_ACCESS_TOKEN and CODEX_ACCESS_TOKEN automatically.
Access to the Codex CLI file is disabled by default. After `codex login`, grant read-only access explicitly with:
`codewhale auth external-consent --provider openai-codex --mode read-only --path {}`
Read-only access never refreshes or rewrites the Codex CLI file. What it means
ApiProvider::OpenaiCodex delegates to oauth::missing_auth_message() (crates/tui/src/oauth.rs:174). Codewhale reads Codex OAuth only from OPENAI_CODEX_ACCESS_TOKEN / CODEX_ACCESS_TOKEN or, with explicit read-only consent, the Codex CLI's auth.json (path interpolated into the message). Access to that file is disabled by default and Codewhale never refreshes or rewrites it, so an expired token must be refreshed by `codex login`.
Source
Thrown at crates/tui/src/config.rs:6409
anyhow::bail!(
"Moonshot/Kimi API key not found. Get a key: {}. Run 'codewhale auth set --provider moonshot', \
set {}, or add [{}] api_key. \
For a Kimi Code plan key, set [providers.moonshot] base_url = \
\"https://api.kimi.com/coding/v1\" and model = \"kimi-for-coding\".",
credential_help
.credential_url
.unwrap_or("https://platform.kimi.ai/console/api-keys"),
provider.env_vars_label(),
provider_config_table_name(provider)?
);
}
ApiProvider::Anthropic | ApiProvider::Openmodel => {
anyhow::bail!("{}", missing_provider_api_key_message(provider)?)
}
ApiProvider::OpencodeZen => {
anyhow::bail!("{}", missing_provider_api_key_message(provider)?)
}
ApiProvider::OpenaiCodex => anyhow::bail!("{}", crate::oauth::missing_auth_message()),
ApiProvider::Xai => {
// Prefer OAuth guidance when auth_mode requests it or Grok CLI
// tokens already exist; otherwise show both API-key and OAuth.
if self
.provider_config_for(provider)
.is_some_and(provider_config_uses_xai_oauth)
|| crate::xai_oauth::credentials_present(self)
{
anyhow::bail!("{}", crate::xai_oauth::missing_auth_message());
}
anyhow::bail!(
"xAI API key not found. Get a key: https://console.x.ai/\n\
Run 'codewhale auth set --provider xai', set XAI_API_KEY, or add \
[providers.xai] api_key.\n\
OAuth alternative: run `codewhale auth xai-device` for \
Codewhale-owned storage and set [providers.xai] auth_mode = \"oauth\"."
);
}View on GitHub (pinned to 8880682c63)
Solutions
- Provide a token via OPENAI_CODEX_ACCESS_TOKEN or CODEX_ACCESS_TOKEN for this process.
- Or after `codex login`, grant read-only access: codewhale auth external-consent --provider openai-codex --mode read-only --path <auth.json path from the message>.
- If the token is expired, run `codex login` again — Codewhale never refreshes the external file.
Example fix
# before: codex login done, but no consent, no env token provider = "openai-codex" # after (terminal) # codewhale auth external-consent --provider openai-codex --mode read-only --path ~/.codex/auth.json # or: export OPENAI_CODEX_ACCESS_TOKEN=...
Defensive patterns
Strategy: fallback
Validate before calling
fn codex_token_available() -> bool {
["OPENAI_CODEX_ACCESS_TOKEN", "CODEX_ACCESS_TOKEN"]
.iter()
.any(|v| std::env::var(v).map(|s| !s.trim().is_empty()).unwrap_or(false))
}
if !codex_token_available() {
// plan B: prompt for external-consent on the Codex CLI auth.json,
// or deselect openai-codex before dispatch
} Type guard
fn codex_oauth_ready(config: &Config) -> bool {
codex_token_available()
|| crate::oauth::stored_credentials_present_if_consented(config) // consent + unexpired token
} Try / catch
match config.deepseek_api_key() {
Err(e) if e.to_string().starts_with("OpenAI Codex OAuth credentials are unavailable") => {
// fall back: another provider route, or surface the external-consent command
Err(e)
}
other => other,
} Prevention
- `codex login` alone is never enough — grant read-only consent explicitly afterwards.
- In CI, prefer OPENAI_CODEX_ACCESS_TOKEN over file consent.
- Expired Codex tokens must be refreshed by codex login; Codewhale never rewrites that file.
When it happens
Trigger: provider = openai-codex with neither env token set, no Codewhale-owned OAuth storage, and no read-only consent for the Codex CLI auth.json; or consent granted but the underlying token expired (a sibling error points back to `codex login`).
Common situations: Users assuming `codex login` alone is enough (consent is a separate step); CI without the env tokens; rotating machines where auth.json exists but was never consented.
Related errors
- external credential access for {} is dormant until that prov
- external credential consent for {}: {error}
- xAI OAuth credentials not found. Options: 1. Run `codewhale
- parallel(): expected an array of thunks
- The Codewhale service returned a verification URL without a
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/dd243e011dcb3c60.
Report an issue: GitHub.