{"record":{"id":"dc9547789282c18f","repo":"zeroclaw-labs/zeroclaw","slug":"gemini-auth-profile-is-not-oauth-based-profile-i","errorCode":null,"errorMessage":"Gemini auth profile is not OAuth-based: {profile_id}","messagePattern":"Gemini auth profile is not OAuth-based: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/auth/mod.rs","lineNumber":303,"sourceCode":"    }\n\n    pub async fn get_valid_gemini_access_token(\n        &self,\n        profile_override: Option<&str>,\n        client_id: &str,\n        client_secret: &str,\n    ) -> Result<Option<String>> {\n        let data = self.store.load().await?;\n        let Some(profile_id) = select_profile_id(&data, GEMINI_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!(\"Gemini 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        // Re-load after waiting for lock to avoid duplicate refreshes.\n        let data = self.store.load().await?;\n        let Some(latest_profile) = data.profiles.get(&profile_id) else {\n            return Ok(None);\n        };","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/auth/mod.rs#L285-L321","documentation":"The Gemini counterpart of error 670: get_valid_gemini_access_token selected a gemini profile whose token_set is None, meaning the stored credential is a bearer token rather than an OAuth token set. The function needs a token_set to check expiry and refresh; a token-kind profile violates that contract and bails.","triggerScenarios":"Calling send_generate_content, warmup, or refresh_status for gemini when the active profile was created via auth paste-token; selecting such a profile through profile_override; a hand-edited or migrated profiles file with a null token_set.","commonSituations":"User pasted an API key for Gemini but the runtime path calls the OAuth resolver; the alias profile in [providers.models.gemini.<profile>] was set up with a token instead of the OAuth login flow.","solutions":["Run auth login --model-provider gemini --profile <name> to complete the Google OAuth flow and store a token_set","Verify you are selecting the right profile: list profiles and their kinds before passing profile_override","If a bearer/API-key profile is intended, route through get_provider_bearer_token instead"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let data = auth.load_profiles().await?;\nif let Some(profile) = data.profiles.get(&format!(\"gemini:{}\", name)) {\n    anyhow::ensure!(profile.token_set.is_some(), \"gemini profile {name} is a bearer token, not OAuth\");\n}\nlet token = auth.get_valid_gemini_access_token(Some(name), client_id, client_secret).await?;","typeGuard":"fn is_oauth_profile(p: &AuthProfile) -> bool {\n    p.token_set.is_some()\n}","tryCatchPattern":"match auth.get_valid_gemini_access_token(override_, cid, secret).await {\n    Ok(tok) => tok,\n    Err(e) if e.to_string().contains(\"not OAuth-based\") => {\n        eprintln!(\"run auth login --model-provider gemini to create an OAuth profile\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use auth login --model-provider gemini for profiles that feed OAuth resolvers","Check token_set presence before calling send_generate_content paths","Keep bearer-token profiles on get_provider_bearer_token"],"tags":["auth","oauth","gemini","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"}