Hmbown/CodeWhale · error · anyhow::Error
agy OAuth token JSON carries no access token member
Error message
agy OAuth token JSON carries no access token member
What it means
The raw agy token value parsed as valid JSON, but none of the accepted members (`access_token`, `accessToken`, `token`) is present as a string. The credential row holds structured data that is not an OAuth token payload, so the importer refuses to guess.
Source
Thrown at crates/tui/src/agy_credentials.rs:224
let Some(raw) = value else {
return Ok(None);
};
let trimmed = raw.trim();
if trimmed.is_empty() {
return Ok(None);
}
if trimmed.starts_with('{') {
let parsed: serde_json::Value = serde_json::from_str(trimmed)
.with_context(|| "agy OAuth token value is malformed JSON")?;
for member in ["access_token", "accessToken", "token"] {
if let Some(token) = parsed.get(member).and_then(|v| v.as_str()) {
if token.trim().is_empty() {
bail!("agy OAuth token member `{member}` is empty");
}
return Ok(Some(token.to_string()));
}
}
bail!("agy OAuth token JSON carries no access token member");
}
Ok(Some(trimmed.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
use codewhale_config::ExternalCredentialReadGrant;
use std::collections::HashMap;
fn grant_for(path: &Path) -> ExternalCredentialReadGrant {
codewhale_config::ExternalCredentialConsentToml::read_only(
codewhale_config::ProviderKind::Antigravity,
ExternalCredentialSource::AgyCli,
path.to_path_buf(),
)
.read_grant(
codewhale_config::ProviderKind::Antigravity,View on GitHub (pinned to 0c42157ee5)
Solutions
- Confirm the agy client is signed in, so the auth row with `access_token` (or `accessToken`/`token`) actually exists, then retry.
- Inspect the stored value (read-only) to see which member names it carries and align the importer with the supported set.
- Update to matching codewhale/agy versions if the payload schema changed.
Example fix
// before
let token = antigravity_oauth_token_from_grant(&grant)?; // bails: no access token member
// after
// verify the payload shape before import
let raw = read_token_row_readonly(grant.path())?; // your read helper
let v: serde_json::Value = serde_json::from_str(&raw)?;
if v.get("access_token").or_else(|| v.get("accessToken")).and_then(|t| t.as_str()).is_none() {
anyhow::bail!("agy client is signed out or uses an unsupported token schema");
}
let token = antigravity_oauth_token_from_grant(&grant)?; Defensive patterns
Strategy: try-catch
Validate before calling
let raw = peek_token_value(grant.path())?;
if let Some(v) = raw.as_deref().filter(|v| v.trim().starts_with('{')) {
let json: serde_json::Value = serde_json::from_str(v.trim())?;
if !["access_token", "accessToken", "token"].iter().any(|m| json.get(*m).is_some()) {
anyhow::bail!("stored payload has no token member; sign in to agy first");
}
} Type guard
fn carries_token_member(v: &serde_json::Value) -> bool {
v.get("access_token").or_else(|| v.get("accessToken")).or_else(|| v.get("token")).is_some()
} Try / catch
match antigravity_oauth_token_from_grant(&grant) {
Ok(t) => t,
Err(e) if e.to_string().contains("no access token member") => { /* schema mismatch or signed out */ return Err(e.context("update codewhale or sign in to agy")) }
Err(e) => return Err(e),
} Prevention
- Keep codewhale and the agy client versions in lockstep so the token payload schema matches.
- Confirm the client is signed in — the auth row only exists after login.
- When introspecting the store read-only, print member names only; never log token values.
When it happens
Trigger: parse_agy_oauth_token_value receives JSON such as `{"version":1,"settings":{...}}` or a token wrapped under a different key (e.g. `{"auth": {...}}`) — the row exists but is not a token record.
Common situations: The agy client changed its schema and stores the token under a new key or table; the grant reads a settings-oriented row instead of the auth row; a future/older client version with a different payload shape.
Related errors
- agy OAuth token member `{member}` is empty
- invalid Codewhale-owned xAI OAuth generation; expected xai-a
- Codewhale-owned xAI OAuth file {} exceeds the {} byte limit
- Antigravity import requires an agy_cli grant, not {}
- external agy credential file {} is not a SQLite database
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/9835fbd863c45fae.
Report an issue: GitHub.