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

  1. Confirm the agy client is signed in, so the auth row with `access_token` (or `accessToken`/`token`) actually exists, then retry.
  2. Inspect the stored value (read-only) to see which member names it carries and align the importer with the supported set.
  3. 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

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


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/9835fbd863c45fae. Report an issue: GitHub.