Hmbown/CodeWhale · error
Codewhale-owned xAI OAuth credentials are inactive until…
Error message
Codewhale-owned xAI OAuth credentials are inactive until the xAI route explicitly selects OAuth
What it means
get_xai_credentials refuses to load Codewhale-owned xAI OAuth credentials unless the active API provider is Xai AND that provider's config explicitly selects an xAI-OAuth auth_mode (checked with auth_mode_uses_xai_oauth). This prevents silently using stored OAuth tokens when the route is configured for API-key auth or a different provider.
Solutions
- Set the xAI provider entry's auth_mode to the OAuth mode in your Codewhale config (or re-run `codewhale auth xai-device`, which configures it).
- If you intend API-key auth, stop relying on OAuth credentials and supply an API key instead.
- Check that the active route actually selects ApiProvider::Xai.
Example fix
// before (config) [xai] auth_mode = "api_key" // after [xai] auth_mode = "oauth" # the xAI-OAuth auth mode accepted by auth_mode_uses_xai_oauth
Defensive patterns
Strategy: validation
Validate before calling
if (cfg.api_provider !== 'xai' || !/^oauth/.test(cfg.providers?.xai?.auth_mode ?? '')) fixAuthMode(cfg);
Type guard
const xaiOauthActive = (cfg) => cfg.api_provider === 'xai' && typeof cfg.providers?.xai?.auth_mode === 'string' && cfg.providers.xai.auth_mode.includes('oauth'); Try / catch
try { getXaiCredentials(); } catch (e) { if (String(e).includes('inactive until the xAI route')) updateConfigAuthMode('oauth'); } Prevention
- Keep auth_mode and the active provider route in sync in config
- Re-run `codewhale auth xai-device` after config changes so it rewrites auth_mode
- Audit config for auth_mode = "api_key" before relying on OAuth credentials
When it happens
Trigger: Calling get_xai_credentials when config.api_provider() != ApiProvider::Xai, or when provider_config_for(Xai).auth_mode is absent or not an xAI-OAuth mode (e.g. "api_key" or unset).
Common situations: User completed `codewhale auth xai-device` but the xAI route in config still specifies api_key auth_mode; config file edited to remove auth_mode; credentials carried over from an experiment while the route points elsewhere.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- invalid Codewhale-owned xAI OAuth generation; expected…
- Codewhale-owned OAuth credentials are not configured
- invalid Codewhale-owned ChatGPT OAuth generation; expected…
- invalid MCP OAuth callback port 0
- Kimi CLI credential import is unsupported. Codewhale does…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/2871ed02884e0f1c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/oauth.rs:2115
"xAI OAuth credentials at {} have no usable entry. Run `grok login` again or use `codewhale auth xai-device` for Codewhale-owned storage.",
codewhale_config::quote_os_path(grant.path())
)
})?;
if !entry_access_token_is_fresh(&entry) {
bail!(
"xAI OAuth access token in {} is expired. Read-only consent never refreshes or rewrites another CLI's credentials. Run `grok login` again or use `codewhale auth xai-device`.",
codewhale_config::quote_os_path(grant.path())
);
}
Ok(())
}
/// Load xAI OAuth credentials with full precedence: configured generation,
/// legacy owned file, then the consented Grok CLI import. Codewhale-owned
/// credentials may refresh and rewrite Codewhale-owned storage; external
/// credentials are read-only.
pub fn get_xai_credentials(config: &Config) -> Result<OwnedOAuthCredentials> {
anyhow::ensure!(
config.api_provider() == crate::config::ApiProvider::Xai
&& config
.provider_config_for(crate::config::ApiProvider::Xai)
.and_then(|entry| entry.auth_mode.as_deref())
.is_some_and(auth_mode_uses_xai_oauth),
"Codewhale-owned xAI OAuth credentials are inactive until the xAI route explicitly selects OAuth"
);
if let Some(owned_path) = configured_owned_auth_file_path(OAuthProvider::Xai, config)? {
return get_owned_credentials_at(OAuthProvider::Xai, &owned_path);
}
let owned_path = codewhale_config::legacy_xai_oauth_path()?;
if load_owned_auth_file(&owned_path)?.is_some() {
return get_owned_credentials_at(OAuthProvider::Xai, &owned_path);
}
let external_path = grok_auth_file_path();
let grant = config.external_credential_read_grant(
crate::config::ApiProvider::Xai,View on GitHub (pinned to 73e0f67d83)