{"record":{"id":"8bd76ba6f1ac28be","repo":"zeroclaw-labs/zeroclaw","slug":"xai-auth-profile-is-not-oauth-based-profile-id","errorCode":null,"errorMessage":"xAI auth profile is not OAuth-based: {profile_id}","messagePattern":"xAI auth profile is not OAuth-based: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/auth/mod.rs","lineNumber":400,"sourceCode":"    }\n\n    /// Return a valid xAI OAuth access token, refreshing it when the cached\n    /// token is close to expiry and a refresh token is available.\n    pub async fn get_valid_xai_access_token(\n        &self,\n        profile_override: Option<&str>,\n    ) -> Result<Option<String>> {\n        let data = self.store.load().await?;\n        let Some(profile_id) = select_profile_id(&data, XAI_PROVIDER, profile_override) else {\n            return Ok(None);\n        };\n\n        let Some(profile) = data.profiles.get(&profile_id) else {\n            return Ok(None);\n        };\n\n        let Some(token_set) = profile.token_set.as_ref() else {\n            anyhow::bail!(\"xAI auth profile is not OAuth-based: {profile_id}\");\n        };\n\n        if !token_set.is_expiring_within(Duration::from_secs(OPENAI_REFRESH_SKEW_SECS)) {\n            return Ok(Some(token_set.access_token.clone()));\n        }\n\n        let Some(refresh_token) = token_set.refresh_token.clone() else {\n            return Ok(Some(token_set.access_token.clone()));\n        };\n\n        let refresh_lock = refresh_lock_for_profile(&profile_id);\n        let _guard = refresh_lock.lock().await;\n\n        let data = self.store.load().await?;\n        let Some(latest_profile) = data.profiles.get(&profile_id) else {\n            return Ok(None);\n        };\n        let Some(latest_tokens) = latest_profile.token_set.as_ref() else {","sourceCodeStart":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/auth/mod.rs#L382-L418","documentation":"The xAI counterpart of errors 670/673: get_valid_xai_access_token selected an xai profile whose token_set is None — the credential is stored as a plain bearer token, but the resolver can only return (and refresh) OAuth token sets. It bails instead of returning a misleading None.","triggerScenarios":"Calling resolve_credential or refresh_status for xai when the active (or overridden) profile was created with auth paste-token / setup-token instead of the xAI OAuth login or --import flow.","commonSituations":"Pasting an xAI API key and then invoking an OAuth-dependent path; selecting a token-kind profile via profile_override; profile file edits that dropped token_set.","solutions":["Run auth login --model-provider xai to perform the OAuth flow, or --import an existing token-set JSON","For pure bearer-token usage, call get_provider_bearer_token(\"xai\", ...) instead","Check the profile kind before passing an override name"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let data = auth.load_profiles().await?;\nif let Some(profile) = data.profiles.get(&format!(\"xai:{}\", name)) {\n    anyhow::ensure!(profile.token_set.is_some(), \"xai profile {name} is a bearer token, not OAuth\");\n}\nlet token = auth.get_valid_xai_access_token(Some(name)).await?;","typeGuard":"fn is_oauth_profile(p: &AuthProfile) -> bool {\n    p.token_set.is_some()\n}","tryCatchPattern":"match auth.get_valid_xai_access_token(override_).await {\n    Ok(tok) => tok,\n    Err(e) if e.to_string().contains(\"not OAuth-based\") => {\n        auth.get_provider_bearer_token(\"xai\", override_).await?.flatten()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Create xai OAuth profiles with auth login --model-provider xai or --import","Pre-check profile.token_set before resolve_credential calls","Route bearer-token profiles through get_provider_bearer_token"],"tags":["auth","oauth","xai","profile","rust"],"backgroundTag":"auth-profile-not-oauth","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}