{"record":{"id":"2d83bf7493cf23c0","repo":"zeroclaw-labs/zeroclaw","slug":"xai-auth-profile-is-missing-token-set-profile-id","errorCode":null,"errorMessage":"xAI auth profile is missing token set: {profile_id}","messagePattern":"xAI auth profile is missing token set: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/auth/mod.rs","lineNumber":419,"sourceCode":"        };\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 {\n            anyhow::bail!(\"xAI auth profile is missing token set: {profile_id}\");\n        };\n        if !latest_tokens.is_expiring_within(Duration::from_secs(OPENAI_REFRESH_SKEW_SECS)) {\n            return Ok(Some(latest_tokens.access_token.clone()));\n        }\n\n        let refresh_token = latest_tokens.refresh_token.clone().unwrap_or(refresh_token);\n        if let Some(remaining) = refresh_backoff_remaining(&profile_id) {\n            anyhow::bail!(\n                \"xAI token refresh is in backoff for {remaining}s due to previous failures\"\n            );\n        }\n\n        let mut refreshed =\n            match refresh_xai_access_token_with_retries(&self.client, &refresh_token).await {\n                Ok(tokens) => {\n                    clear_refresh_backoff(&profile_id);\n                    tokens\n                }","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/auth/mod.rs#L401-L437","documentation":"Post-lock twin of error 676 in get_valid_xai_access_token: after acquiring the per-profile refresh lock, the re-loaded profile no longer carries a token_set. A concurrent write changed the profile from OAuth to token kind (or removed the set) between the two store loads inside this resolver.","triggerScenarios":"resolve_credential runs while the same xai profile is overwritten by a concurrent paste-token or external edit; the first load sees a token_set, the second does not, and the call bails.","commonSituations":"Shared state dir between CLI and long-running process; parallel scripts rewriting the profiles file.","solutions":["Retry once the profile write settles","Use one state dir per process so the profiles file has a single writer","Keep the xai profile on one credential kind instead of switching it while traffic runs"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"let data = auth.load_profiles().await?;\nanyhow::ensure!(\n    data.profiles.get(&profile_id).map(|p| p.token_set.is_some()).unwrap_or(false),\n    \"xai profile lost its token set mid-flight\"\n);","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(\"missing token set\") => {\n        tokio::time::sleep(std::time::Duration::from_millis(500)).await;\n        auth.get_valid_xai_access_token(override_).await?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Avoid concurrent profile writes from CLI and gateway on one state dir","Retry once after the racing write completes","Keep the xai profile on a single credential kind"],"tags":["auth","oauth","xai","race-condition","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"}