googleworkspace/cli · error

GOOGLE_APPLICATION_CREDENTIALS points to {adc_env}, but file

Error message

GOOGLE_APPLICATION_CREDENTIALS points to {adc_env}, but file does not exist

What it means

Credential resolution step 4a honors the standard GOOGLE_APPLICATION_CREDENTIALS variable. Like the gws-specific variable, an explicitly set path that does not exist is a hard error: silently skipping user-mandated ADC would mask the misconfiguration and fall through to a confusing 'no credentials' failure later.

Source

Thrown at crates/google-workspace-cli/src/auth.rs:412

        return Ok(Credential::AuthorizedUser(
            yup_oauth2::read_authorized_user_secret(default_path)
                .await
                .with_context(|| {
                    format!("Failed to read credentials from {}", default_path.display())
                })?,
        ));
    }

    // 4a. GOOGLE_APPLICATION_CREDENTIALS env var (explicit path — hard error if missing)
    if let Ok(adc_env) = std::env::var("GOOGLE_APPLICATION_CREDENTIALS") {
        let adc_path = PathBuf::from(&adc_env);
        if adc_path.exists() {
            let content = tokio::fs::read_to_string(&adc_path)
                .await
                .with_context(|| format!("Failed to read ADC from {adc_env}"))?;
            return parse_credential_file(&adc_path, &content).await;
        }
        anyhow::bail!(
            "GOOGLE_APPLICATION_CREDENTIALS points to {adc_env}, but file does not exist"
        );
    }

    // 4b. Well-known ADC path: ~/.config/gcloud/application_default_credentials.json
    // (populated by `gcloud auth application-default login`). Silent if absent.
    if let Some(well_known) = adc_well_known_path() {
        if well_known.exists() {
            let content = tokio::fs::read_to_string(&well_known)
                .await
                .with_context(|| format!("Failed to read ADC from {}", well_known.display()))?;
            return parse_credential_file(&well_known, &content).await;
        }
    }

    anyhow::bail!(
        "No credentials found. Run `gws auth setup` to configure, \
         `gws auth login` to authenticate, or set GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE.\n\

View on GitHub (pinned to a3768d0e82)

Solutions

  1. Verify with: printf '%s\n' "$GOOGLE_APPLICATION_CREDENTIALS" && ls -la "$GOOGLE_APPLICATION_CREDENTIALS"
  2. Fix the path to an absolute one that exists in the runtime environment
  3. If ADC was revoked, re-run `gcloud auth application-default login` to regenerate the well-known file
  4. If ADC is not wanted, unset the variable so gws falls back to its own credentials

Example fix

# before (unexpanded HOME in a systemd unit)
Environment=GOOGLE_APPLICATION_CREDENTIALS=~/.config/gcp/sa.json

# after
Environment=GOOGLE_APPLICATION_CREDENTIALS=/home/youruser/.config/gcp/sa.json
Defensive patterns

Strategy: validation

Validate before calling

// Preflight ADC before running the real workload
if let Ok(p) = std::env::var("GOOGLE_APPLICATION_CREDENTIALS") {
    assert!(std::path::Path::new(&p).is_file(),
        "GOOGLE_APPLICATION_CREDENTIALS={p} does not exist");
} else if !std::path::Path::new(&format!("{}/.config/gcloud/application_default_credentials.json", std::env::var("HOME").unwrap_or_default())).exists() {
    eprintln!("warning: no ADC configured — run `gcloud auth application-default login` first");
}

Prevention

When it happens

Trigger: Variable points to a file absent from the current container/runner; path with unexpanded ~ or $HOME; wrong quoting in systemd units, cron, or docker; file removed after `gcloud auth application-default revoke`.

Common situations: Kubernetes secret not mounted at the path the env var references; cron job environment missing HOME expansion; stale env var left in a shell profile after the JSON was deleted; CI base image changed and no longer copies the file.

Related errors


AI-assisted analysis of googleworkspace/cli@a3768d0e82 (2026-08-16). Data as JSON: /api/errors/d9f80d16fff88288. Report an issue: GitHub.