zeroclaw-labs/zeroclaw · error
xAI auth profile is not OAuth-based: {profile_id}
Error message
xAI auth profile is not OAuth-based: {profile_id} What it means
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.
Source
Thrown at crates/zeroclaw-providers/src/auth/mod.rs:400
}
/// Return a valid xAI OAuth access token, refreshing it when the cached
/// token is close to expiry and a refresh token is available.
pub async fn get_valid_xai_access_token(
&self,
profile_override: Option<&str>,
) -> Result<Option<String>> {
let data = self.store.load().await?;
let Some(profile_id) = select_profile_id(&data, XAI_PROVIDER, profile_override) else {
return Ok(None);
};
let Some(profile) = data.profiles.get(&profile_id) else {
return Ok(None);
};
let Some(token_set) = profile.token_set.as_ref() else {
anyhow::bail!("xAI auth profile is not OAuth-based: {profile_id}");
};
if !token_set.is_expiring_within(Duration::from_secs(OPENAI_REFRESH_SKEW_SECS)) {
return Ok(Some(token_set.access_token.clone()));
}
let Some(refresh_token) = token_set.refresh_token.clone() else {
return Ok(Some(token_set.access_token.clone()));
};
let refresh_lock = refresh_lock_for_profile(&profile_id);
let _guard = refresh_lock.lock().await;
let data = self.store.load().await?;
let Some(latest_profile) = data.profiles.get(&profile_id) else {
return Ok(None);
};
let Some(latest_tokens) = latest_profile.token_set.as_ref() else {View on GitHub (pinned to 88bb9c8533)
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
Defensive patterns
Strategy: validation
Validate before calling
let data = auth.load_profiles().await?;
if let Some(profile) = data.profiles.get(&format!("xai:{}", name)) {
anyhow::ensure!(profile.token_set.is_some(), "xai profile {name} is a bearer token, not OAuth");
}
let token = auth.get_valid_xai_access_token(Some(name)).await?; Type guard
fn is_oauth_profile(p: &AuthProfile) -> bool {
p.token_set.is_some()
} Try / catch
match auth.get_valid_xai_access_token(override_).await {
Ok(tok) => tok,
Err(e) if e.to_string().contains("not OAuth-based") => {
auth.get_provider_bearer_token("xai", override_).await?.flatten()
}
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- xAI auth profile is missing token set: {profile_id}
- OpenAI Codex auth profile is not OAuth-based: {profile_id}
- OpenAI Codex auth profile is missing token set: {profile_id}
- Gemini auth profile is not OAuth-based: {profile_id}
- Gemini auth profile is missing token set: {profile_id}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/8bd76ba6f1ac28be.
Report an issue: GitHub.