googleworkspace/cli · error
Failed to write credentials: {e}
Error message
Failed to write credentials: {e} What it means
The final persistence step in save: after encrypting the JSON, the bytes are written via atomic_write (sibling .tmp + rename). This error wraps any failure of that write — permission denied on the config dir, read-only filesystem, disk full, or the target path being unusable. The atomic strategy means the previous credentials file is never left half-written by these failures.
Source
Thrown at crates/google-workspace-cli/src/credential_store.rs:453
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
if let Err(e) = std::fs::set_permissions(parent, std::fs::Permissions::from_mode(0o700))
{
eprintln!(
"Warning: failed to set directory permissions on {}: {e}",
parent.display()
);
}
}
}
let encrypted = encrypt(json.as_bytes())?;
// Write atomically via a sibling .tmp file + rename so the credentials
// file is never left in a corrupt partial-write state on crash/Ctrl-C.
crate::fs_util::atomic_write(&path, &encrypted)
.map_err(|e| anyhow::anyhow!("Failed to write credentials: {e}"))?;
Ok(path)
}
/// Loads and decrypts credentials JSON from a specific path.
pub fn load_encrypted_from_path(path: &std::path::Path) -> anyhow::Result<String> {
let data = std::fs::read(path)?;
let plaintext = decrypt(&data)?;
Ok(String::from_utf8(plaintext)?)
}
/// Loads and decrypts credentials JSON from the default encrypted file.
pub fn load_encrypted() -> anyhow::Result<String> {
load_encrypted_from_path(&encrypted_credentials_path())
}
#[cfg(test)]
mod tests {View on GitHub (pinned to a3768d0e82)
Solutions
- Check ownership: `ls -ld ~/.config/gws` and fix with chown if it is owned by root
- Verify writability: `touch ~/.config/gws/.probe` (or your GOOGLE_WORKSPACE_CLI_CONFIG_DIR) and check disk space with `df -h`
- Point GOOGLE_WORKSPACE_CLI_CONFIG_DIR at a writable directory, or fix the mount options / SELinux policy
Example fix
# before $ sudo gws auth login # creates root-owned ~/.config/gws $ gws auth login # Failed to write credentials # after $ sudo chown -R "$USER:$USER" ~/.config/gws $ gws auth login
Defensive patterns
Strategy: validation
Validate before calling
// Preflight: prove the config dir is writable before login
use std::io::Write;
fn config_dir_writable(dir: &std::path::Path) -> bool {
std::fs::create_dir_all(dir).is_ok() && {
let probe = dir.join(".write_probe");
std::fs::File::create(&probe).and_then(|mut f| f.write_all(b"x")).is_ok()
&& std::fs::remove_file(&probe).is_ok()
}
} Prevention
- Never run gws with sudo as a habit — it leaves root-owned files in ~/.config/gws
- Check `df -h` and `ls -ld` on the config dir as part of provisioning scripts
- Mount a writable volume at GOOGLE_WORKSPACE_CLI_CONFIG_DIR in containers
When it happens
Trigger: ~/.config/gws owned by root after running gws with sudo; GOOGLE_WORKSPACE_CLI_CONFIG_DIR pointing at a read-only mount; disk quota exhausted; directory in the path replaced by a file; SELinux denying writes.
Common situations: Ran `sudo gws auth login` once, then normal user cannot write; container with a read-only config mount; CI runner with a full disk; config dir on a hardened NFS mount.
Related errors
- GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE points to {path}, but
- GOOGLE_APPLICATION_CREDENTIALS points to {adc_env}, but file
- No credentials found. Run `gws auth setup` to configure, `gw
- OS keyring failed: {}. Set GOOGLE_WORKSPACE_CLI_KEYRING_BACK
- Failed to set key in OS keyring: {}
AI-assisted analysis of googleworkspace/cli@a3768d0e82 (2026-08-16).
Data as JSON: /api/errors/9d01d7053102770e.
Report an issue: GitHub.