googleworkspace/cli · error

GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE points to {path}, but

Error message

GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE points to {path}, but file does not exist

What it means

During credential resolution, step 1 honors GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE as an explicit plaintext credential path (authorized_user or service_account JSON). Because the variable is explicitly set, a missing file is a hard error rather than a silent fallthrough — the CLI refuses to silently continue with weaker credentials than the operator asked for.

Source

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

        })?;
    Ok(Credential::AuthorizedUser(secret))
}

async fn load_credentials_inner(
    env_file: Option<&str>,
    enc_path: &std::path::Path,
    default_path: &std::path::Path,
) -> anyhow::Result<Credential> {
    // 1. Explicit env var — plaintext file (User or Service Account)
    if let Some(path) = env_file {
        let p = PathBuf::from(path);
        if p.exists() {
            let content = tokio::fs::read_to_string(&p)
                .await
                .with_context(|| format!("Failed to read credentials from {path}"))?;
            return parse_credential_file(&p, &content).await;
        }
        anyhow::bail!(
            "GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE points to {path}, but file does not exist"
        );
    }

    // 2. Encrypted credentials
    if enc_path.exists() {
        match credential_store::load_encrypted_from_path(enc_path) {
            Ok(json_str) => {
                return parse_credential_file(enc_path, &json_str).await;
            }
            Err(e) => {
                // Decryption failed — the encryption key likely changed (e.g. after
                // an upgrade that migrated keys between keyring and file storage).
                // Remove the stale file so the next `gws auth login` starts fresh,
                // and fall through to other credential sources (plaintext, ADC).
                eprintln!(
                    "Warning: removing undecryptable credentials file ({}): {e:#}",
                    enc_path.display()

View on GitHub (pinned to a3768d0e82)

Solutions

  1. Echo the variable and run `ls -la` on the exact value to see what the shell actually resolves
  2. Use an absolute path (e.g. /home/user/creds.json or /run/secrets/creds.json) — not ~ or a relative path
  3. In .env files, expand manually: GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/home/user/creds.json
  4. If the file was never intended as plaintext, unset the variable and use `gws auth login` encrypted credentials instead

Example fix

# before (.env — tilde is NOT expanded by dotenvy)
GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=~/gcp/creds.json

# after
GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/home/youruser/gcp/creds.json
Defensive patterns

Strategy: validation

Validate before calling

// Run before invoking gws / the credential resolver
if let Ok(p) = std::env::var("GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE") {
    let path = std::path::Path::new(&p);
    assert!(path.is_file(), "GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE={p} does not exist — use an absolute path");
}

Prevention

When it happens

Trigger: Typo in the path; relative path resolved against an unexpected working directory; '~/creds.json' written inside a .env file (dotenvy does not expand ~); file deleted or never created; wrong shell quoting in CI.

Common situations: CI job sets the variable via a secret that references a path not present in the runner image; a .env entry uses a tilde or unexpanded $HOME; the credential file is gitignored and missing after a fresh clone; docker-compose env lacks the mounted volume containing the file.

Related errors


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