Hmbown/CodeWhale · error · anyhow::Error

Antigravity import requires an agy_cli grant, not {}

Error message

Antigravity import requires an agy_cli grant, not {}

What it means

antigravity_oauth_token_from_grant in crates/tui/src/agy_credentials.rs refuses to read Antigravity credentials unless the ExternalCredentialReadGrant's source is exactly ExternalCredentialSource::AgyCli. Grants for other sources (process-env AGY_ADC_AUTH, generic external files, none) name different credential stores, so reading an agy OAuth token from them is a programming/consent mistake and is rejected up front.

Source

Thrown at crates/tui/src/agy_credentials.rs:81

impl AntigravityCredential {
    #[must_use]
    pub fn source_label(&self) -> &'static str {
        match self {
            Self::OwnedKey(_) => "ANTIGRAVITY_API_KEY",
            Self::ProcessEnv(_) => "AGY_ADC_AUTH",
            Self::ExternalFile(_) => "agy state.vscdb (read-only)",
            Self::None | Self::Error(_) => "none",
        }
    }
}

/// Extract the `agy` OAuth token from a granted `state.vscdb`.
pub(crate) fn antigravity_oauth_token_from_grant(
    grant: &ExternalCredentialReadGrant,
) -> Result<Option<String>> {
    if grant.source() != ExternalCredentialSource::AgyCli {
        bail!(
            "Antigravity import requires an agy_cli grant, not {}",
            grant.source().as_str()
        );
    }
    let path = grant.path();
    // Secure-open the exact granted path first: regular file only, no
    // symlink/reparse-point leaf, size-capped before any SQLite parsing.
    let mut file = crate::external_credentials::open_external_regular_file(path)?;
    let mut header = [0u8; 16];
    let read = file.read(&mut header).with_context(|| {
        format!(
            "reading SQLite header of {}",
            codewhale_config::quote_os_path(path)
        )
    })?;
    if read < 16 || header[..15] != *b"SQLite format 3" {
        bail!(
            "external agy credential file {} is not a SQLite database",

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Build the grant from an explicit read-only consent entry (ExternalCredentialConsentToml::read_only) whose source resolves to agy_cli, pointing at the agy `state.vscdb`.
  2. Guard before calling: `if grant.source() != ExternalCredentialSource::AgyCli { /* prompt for consent instead */ }`.
  3. If you meant to use an env token, use the process-env credential path — not this function.

Example fix

// before
let token = antigravity_oauth_token_from_grant(&grant)?; // bails: not an agy_cli grant

// after
if grant.source() != ExternalCredentialSource::AgyCli {
    anyhow::bail!("prompt the user for a read-only agy state.vscdb grant");
}
let token = antigravity_oauth_token_from_grant(&grant)?;
Defensive patterns

Strategy: type-guard

Validate before calling

if grant.source() != ExternalCredentialSource::AgyCli {
    anyhow::bail!("Antigravity import needs a read-only agy state.vscdb grant; current source: {}", grant.source().as_str());
}

Type guard

fn is_agy_cli_grant(grant: &ExternalCredentialReadGrant) -> bool {
    grant.source() == ExternalCredentialSource::AgyCli
}

Try / catch

match antigravity_oauth_token_from_grant(&grant) {
    Ok(token) => token,
    Err(e) if e.to_string().contains("requires an agy_cli grant") => { /* request consent, then retry */ None }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling antigravity_oauth_token_from_grant(&grant) where grant.source() returns ExternalCredentialSource::ProcessEnv, ExternalCredentialSource::ExternalFile for a non-agy path, or None — e.g. the import flow was handed the ambient AGY_ADC_AUTH env grant or no grant at all.

Common situations: Wiring the wrong consent grant into the Antigravity import command; a CLI flag that resolves the default env-based credential instead of requiring an explicit read-only grant on the agy `state.vscdb`; version changes that split grant sources into distinct enum variants.

Related errors


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