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

  1. Run `gcloud auth application-default login` for local development.
  2. Set GOOGLE_APPLICATION_CREDENTIALS to a valid, readable service-account JSON file.
  3. If using SOPS_GCP_CREDENTIALS, ensure it contains the full service-account JSON, not a file path.
  4. 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

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


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/1cf1aaadb7e9a43e. Report an issue: GitHub.