getsops/sops · error
credentials: failed to obtain credentials from %q: %w
Error message
credentials: failed to obtain credentials from %q: %w
What it means
When no token source or credential JSON is configured, newKMSClient falls back to fetching Google credentials from the environment (SOPS_GCP_CREDENTIALS, then ADC). This error wraps the failure of that lookup, meaning SOPS found no usable Google credentials at all.
Source
Thrown at gcpkms/keysource.go:306
// It returns an error if the ResourceID is invalid, or if the setup of the
// client fails.
func (key *MasterKey) newKMSClient(ctx context.Context) (*kms.KeyManagementClient, error) {
re := regexp.MustCompile(`^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$`)
matches := re.FindStringSubmatch(key.ResourceID)
if matches == nil {
return nil, fmt.Errorf("no valid resource ID found in %q", key.ResourceID)
}
var opts []option.ClientOption
switch {
case key.tokenSource != nil:
opts = append(opts, option.WithTokenSource(key.tokenSource))
case key.credentialJSON != nil:
opts = append(opts, option.WithCredentialsJSON(key.credentialJSON))
default:
credentials, err := getGoogleCredentials()
if err != nil {
return nil, fmt.Errorf("credentials: failed to obtain credentials from %q: %w", SopsGoogleCredentialsEnv, err)
}
if credentials != nil {
opts = append(opts, option.WithCredentialsJSON(credentials))
break
}
if atCredentials := getGoogleOAuthTokenFromEnv(); atCredentials != nil {
opts = append(opts, option.WithTokenSource(atCredentials))
break
}
}
switch {
case key.grpcConn != nil:
opts = append(opts, option.WithGRPCConn(key.grpcConn))
case len(key.grpcDialOpts) > 0:
for _, opt := range key.grpcDialOpts {
opts = append(opts, option.WithGRPCDialOption(opt))View on GitHub (pinned to 13442bb981)
Solutions
- Run `gcloud auth application-default login` for local development.
- Set GOOGLE_APPLICATION_CREDENTIALS to a valid, readable service-account JSON file.
- If using SOPS_GCP_CREDENTIALS, ensure it contains the full service-account JSON, not a file path.
- In GKE/Cloud Run/CI-on-GCP, attach a service account via Workload Identity instead of key files.
Example fix
// before // (no credentials configured) // after export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/sops-sa.json"
Defensive patterns
Strategy: validation
Validate before calling
hasCreds := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") != "" || os.Getenv("SOPS_GCP_CREDENTIALS") != ""
if !hasCreds {
// optionally check ~/.config/gcloud/application_default_credentials.json exists
return errors.New("no GCP credentials configured for sops")
} Type guard
null
Try / catch
null
Prevention
- Standardize on Workload Identity in GCP environments to avoid key files entirely.
- Document required env vars (GOOGLE_APPLICATION_CREDENTIALS or SOPS_GCP_CREDENTIALS) in CI templates.
- Validate credential JSON parses as JSON in a preflight step.
When it happens
Trigger: newKMSClient's default branch: key.tokenSource == nil, key.credentialJSON == nil, and getGoogleCredentials() returns an error (no SopsGoogleCredentialsEnv value parseable, and google.FindDefaultCredentials fails).
Common situations: Running sops in CI containers with no GOOGLE_APPLICATION_CREDENTIALS and no metadata server; SOPS_GCP_CREDENTIALS set but pointing to unreadable file or invalid JSON; gcloud user credentials never authorized via `gcloud auth application-default login`.
Related errors
- cannot create GCP KMS service: %w
- failed to parse command %s: %w
- failed to execute command %s: %w
- failed to open %s file: %w
- user config directory could not be determined: %w
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/1cf1aaadb7e9a43e.
Report an issue: GitHub.