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

  1. Run auth login --model-provider openai-codex (browser or --device-code) to store a real OAuth token set for that profile
  2. Or import existing credentials: auth login --model-provider openai-codex --import ~/.codex/auth.json
  3. 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

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


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/ad21d9ade72ed942. Report an issue: GitHub.