zeroclaw-labs/zeroclaw · error
OpenAI Codex auth profile is not OAuth-based: {profile_id}
Error message
OpenAI Codex auth profile is not OAuth-based: {profile_id} What it means
get_valid_openai_access_token selected a profile for openai-codex, but the profile has no token_set — its credential was stored as a plain bearer token (AuthProfileKind::Token, created by auth paste-token / setup-token) rather than an OAuth token set. The function's contract is to return a refreshable OAuth access token, so a token-kind profile is a hard error rather than a None.
Source
Thrown at crates/zeroclaw-providers/src/auth/mod.rs:215
Ok(credential.filter(|t| !t.trim().is_empty()))
}
pub async fn get_valid_openai_access_token(
&self,
profile_override: Option<&str>,
) -> Result<Option<String>> {
let data = self.store.load().await?;
let Some(profile_id) = select_profile_id(&data, OPENAI_CODEX_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!("OpenAI Codex 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;
// Re-load after waiting for lock to avoid duplicate refreshes.
let data = self.store.load().await?;
let Some(latest_profile) = data.profiles.get(&profile_id) else {
return Ok(None);
};View on GitHub (pinned to 88bb9c8533)
Solutions
- Run auth login --model-provider openai-codex (browser or --device-code) to store a real OAuth token set for that profile
- Or import existing credentials: auth login --model-provider openai-codex --import ~/.codex/auth.json
- If a bearer token is intended, use get_provider_bearer_token instead of get_valid_openai_access_token
Example fix
// before
let token = auth.get_valid_openai_access_token(None).await?; // errors on token-kind profile
// after
let token = match auth.get_valid_openai_access_token(None).await {
Ok(t) => t,
Err(e) if e.to_string().contains("not OAuth-based") => {
auth.get_provider_bearer_token("openai-codex", None).await?.flatten()
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: validation
Validate before calling
// Verify the selected profile is OAuth-based before asking for a valid token.
let data = auth.load_profiles().await?;
if let Some(profile) = data.profiles.get(&format!("openai-codex:{}", name)) {
anyhow::ensure!(profile.token_set.is_some(), "profile {name} is a bearer token, not OAuth");
}
let token = auth.get_valid_openai_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_openai_access_token(override_).await {
Ok(tok) => tok,
Err(e) if e.to_string().contains("not OAuth-based") => {
// credential was stored as a bearer token; either re-login or use the bearer path
auth.get_provider_bearer_token("openai-codex", override_).await?.flatten()
}
Err(e) => return Err(e),
} Prevention
- Create codex profiles with auth login (or --import) when OAuth refresh is required
- Check profile.token_set.is_some() before calling the OAuth resolver
- Use get_provider_bearer_token for paste-token profiles
When it happens
Trigger: Calling resolve_credentials or refresh_status for openai-codex after the active profile was created with auth paste-token (token kind); importing or hand-editing an auth profile file so token_set is null while kind stays OAuth.
Common situations: User pasted an API key for codex, then ran an operation that requires the OAuth flow; profile file migrated or edited and the token_set field was dropped; wrong profile selected via profile_override.
Related errors
- OpenAI Codex auth profile is missing token set: {profile_id}
- OpenAI token refresh is in backoff for {remaining}s due to p
- Gemini auth profile is not OAuth-based: {profile_id}
- Gemini auth profile is missing token set: {profile_id}
- xAI auth profile is not OAuth-based: {profile_id}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/ad21d9ade72ed942.
Report an issue: GitHub.