{"record":{"id":"e6816a6898bd5035","repo":"googleworkspace/cli","slug":"os-keyring-failed-set-google-workspace-cli-ke","errorCode":null,"errorMessage":"OS keyring failed: {}. Set GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file to use file storage.","messagePattern":"OS keyring failed: (.+?)\\. Set GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file to use file storage\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/google-workspace-cli/src/credential_store.rs","lineNumber":233,"sourceCode":"                            if let Err(e) = std::fs::remove_file(key_file) {\n                                if e.kind() != std::io::ErrorKind::NotFound {\n                                    eprintln!(\n                                        \"Warning: failed to remove legacy key file at '{}': {}\",\n                                        key_file.display(),\n                                        e\n                                    );\n                                }\n                            }\n                            return Ok(arr);\n                        }\n                    }\n                    // Keyring contained invalid data — fall through to generate new.\n                }\n                Err(keyring::Error::NoEntry) => {\n                    // Keyring is empty — fall through to generate new.\n                }\n                Err(e) => {\n                    anyhow::bail!(\"OS keyring failed: {}. Set GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file to use file storage.\", sanitize_for_terminal(&e.to_string()));\n                }\n            }\n\n            // Generate a new key if keyring was empty or contained invalid data.\n            let key = generate_random_key();\n            let b64_key = STANDARD.encode(key);\n            if let Err(e) = provider.set_password(&b64_key) {\n                anyhow::bail!(\n                    \"Failed to set key in OS keyring: {}\",\n                    sanitize_for_terminal(&e.to_string())\n                );\n            }\n            if let Err(e) = std::fs::remove_file(key_file) {\n                if e.kind() != std::io::ErrorKind::NotFound {\n                    eprintln!(\n                        \"Warning: failed to remove legacy key file at '{}': {}\",\n                        key_file.display(),\n                        e","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/googleworkspace/cli/blob/a3768d0e82ad83cca2da97724e46bea4ff0e6dbd/crates/google-workspace-cli/src/credential_store.rs#L215-L251","documentation":"In the keyring backend, reading the stored base64 AES key from the OS keyring returned an error other than NoEntry — i.e. the keyring service itself failed (no Secret Service on headless Linux, locked macOS keychain, dbus/session problems, Windows credential manager faults). The message suggests switching to the file backend, which is the supported escape hatch for headless and container environments.","triggerScenarios":"Linux without gnome-keyring/xcwd Secret Service running (common in Docker, WSL without systemd, SSH sessions); dbus session not exported (DBUS_SESSION_BUS_ADDRESS unset); macOS keychain locked during non-interactive SSH; keyring entry corrupted by another application.","commonSituations":"Running gws in Docker/CI where no keyring daemon exists; first use inside an SSH session on a Mac; minimal Linux window-manager setups; hardened machines where the secret service is disabled.","solutions":["Export GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file to store the key in a file instead of the OS keyring","On headless Linux, install and start a Secret Service provider (gnome-keyring + dbus) and export DBUS_SESSION_BUS_ADDRESS","On macOS over SSH, unlock the login keychain or switch to the file backend","Set the variable permanently in the environment or .env file for containers"],"exampleFix":"# before\n$ gws drive files list\nError: OS keyring failed: Platform specific ... Set GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file\n\n# after\n$ export GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file\n$ gws drive files list","handlingStrategy":"fallback","validationCode":"// Probe keyring availability once at startup and select the backend explicitly\nfn pick_backend() -> &'static str {\n    let backend = std::env::var(\"GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND\").unwrap_or_default();\n    if backend.is_empty() && std::env::var_os(\"DBUS_SESSION_BUS_ADDRESS\").is_none() && cfg!(target_os = \"linux\") {\n        return \"file\"; // headless: avoid OS keyring entirely\n    }\n    \"keyring\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file in Dockerfiles, CI runners, and headless hosts by default","Ensure DBUS_SESSION_BUS_ADDRESS is exported in SSH sessions that must use the Secret Service","Test the exact container image once with `gws auth login` before shipping it"],"tags":["keyring","credentials","headless","docker","config"],"backgroundTag":"os-keyring-unavailable","analyzedSha":"a3768d0e82ad83cca2da97724e46bea4ff0e6dbd","analyzedAt":"2026-08-16T19:51:46.516Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}