{"record":{"id":"61885e7521bf838b","repo":"Hmbown/CodeWhale","slug":"xai-oauth-access-token-in-is-expired-read-only","errorCode":null,"errorMessage":"xAI OAuth access token in {} is expired. Read-only consent never refreshes or rewrites another CLI's credentials. Run `grok login` again or use `codewhale auth xai-device`.","messagePattern":"xAI OAuth access token in (.+?) is expired\\. Read-only consent never refreshes or rewrites another CLI's credentials\\. Run `grok login` again or use `codewhale auth xai-device`\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/xai_oauth.rs","lineNumber":395,"sourceCode":"    if load_owned_auth_file(&owned_path)?.is_some() {\n        return get_owned_credentials(&owned_path);\n    }\n\n    let external_path = auth_file_path();\n    let grant = config.external_credential_read_grant(\n        ApiProvider::Xai,\n        codewhale_config::ExternalCredentialSource::GrokCli,\n        &external_path,\n    )?;\n    let mut file = load_external_auth_file(&grant)?;\n    let (scope, entry) = select_entry(&mut file).ok_or_else(|| {\n        anyhow::anyhow!(\n            \"xAI OAuth credentials at {} have no usable entry. Run `grok login` again or use `codewhale auth xai-device` for Codewhale-owned storage.\",\n            codewhale_config::quote_os_path(grant.path())\n        )\n    })?;\n    if !entry_access_token_is_fresh(&entry) {\n        bail!(\n            \"xAI OAuth access token in {} is expired. Read-only consent never refreshes or rewrites another CLI's credentials. Run `grok login` again or use `codewhale auth xai-device`.\",\n            codewhale_config::quote_os_path(grant.path())\n        );\n    }\n    let token = entry\n        .key\n        .clone()\n        .filter(|token| !token.trim().is_empty())\n        .context(\"xAI OAuth access token is empty\")?;\n    Ok(credentials_from_entry(scope, &entry, token))\n}\n\nfn get_owned_credentials(path: &Path) -> Result<XaiOAuthCredentials> {\n    let directory = codewhale_config::xai_oauth_credentials_dir()?;\n    anyhow::ensure!(\n        path.parent() == Some(directory.as_path()),\n        \"Codewhale-owned xAI OAuth path escaped the credentials directory\"\n    );","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/xai_oauth.rs#L377-L413","documentation":"Error \"xAI OAuth access token in {} is expired. Read-only consent never refreshes or rewrites another CLI's credentials. Run `grok login` again or use `codewhale auth xai-device`.\" thrown in Hmbown/CodeWhale.","triggerScenarios":"Thrown at crates/tui/src/xai_oauth.rs:395 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Run `grok login` again to obtain fresh read-only credentials in the external file","Use `codewhale auth xai-device` to establish CodeWhale-owned device credentials that can refresh","Switch to owned credentials stored under the CodeWhale home so rotation is managed"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}