getsops/sops · error

cannot create GCP KMS service: %w

Error message

cannot create GCP KMS service: %w

What it means

SOPS wraps any error returned while constructing the Google Cloud KMS client during encryption. It is not a key permission problem; it means the client object itself could not be built (bad credentials, bad options, bad endpoint/universe domain, or an invalid resource ID surfaced early). The wrapped error (%w) holds the real cause.

Source

Thrown at gcpkms/keysource.go:174

func (c ClientOptions) ApplyToMasterKey(key *MasterKey) {
	key.clientOpts = c
}

// Encrypt takes a SOPS data key, encrypts it with GCP KMS, and stores the
// result in the EncryptedKey field.
//
// Consider using EncryptContext instead.
func (key *MasterKey) Encrypt(dataKey []byte) error {
	return key.EncryptContext(context.Background(), dataKey)
}

// EncryptContext takes a SOPS data key, encrypts it with GCP KMS, and stores the
// result in the EncryptedKey field.
func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error {
	service, err := key.newKMSClient(ctx)
	if err != nil {
		log.WithField("resourceID", key.ResourceID).Info("Encryption failed")
		return fmt.Errorf("cannot create GCP KMS service: %w", err)
	}
	defer func() {
		if err := service.Close(); err != nil {
			log.Error("failed to close GCP KMS client connection")
		}
	}()

	req := &kmspb.EncryptRequest{
		Name:      key.ResourceID,
		Plaintext: dataKey,
	}
	resp, err := service.Encrypt(ctx, req)
	if err != nil {
		log.WithField("resourceID", key.ResourceID).Info("Encryption failed")
		return fmt.Errorf("failed to encrypt sops data key with GCP KMS key: %w", err)
	}
	// NB: base64 encoding is for compatibility with SOPS <=3.8.x.
	// The previous GCP KMS client used to work with base64 encoded

View on GitHub (pinned to 13442bb981)

Solutions

  1. Inspect the wrapped error and fix credentials: set GOOGLE_APPLICATION_CREDENTIALS to a valid service-account JSON or use Workload Identity/ADC.
  2. If using SOPS_GCP_CREDENTIALS (SopsGoogleCredentialsEnv), validate it is well-formed service-account JSON.
  3. Verify key.ResourceID matches projects/PROJECT/locations/LOC/keyRings/RING/cryptoKeys/KEY exactly.
  4. If using custom endpoint/universe domain env vars, confirm they point at a reachable, valid KMS endpoint.

Example fix

// before: client built with no credentials available
export SOPS_GCP_CREDENTIALS=""
// after
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/sa-key.json  # or rely on ADC/Workload Identity
Defensive patterns

Strategy: try-catch

Validate before calling

if os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") == "" {
    if _, err := os.Stat("/path/to/sa.json"); err != nil {
        t.Fatal("no GCP credentials available")
    }
}
re := regexp.MustCompile(`^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$`)
if !re.MatchString(key.ResourceID) { /* fix ResourceID first */ }

Type guard

null

Try / catch

if err := key.EncryptContext(ctx, dataKey); err != nil {
    if strings.Contains(err.Error(), "cannot create GCP KMS service") {
        // inspect wrapped cause: fix credentials/ADC before retrying
    }
    return err
}

Prevention

When it happens

Trigger: Calling MasterKey.EncryptContext (sops/gcpkms) when key.newKMSClient fails: getGoogleCredentials returns nothing usable and ADC fails, invalid credentialJSON, or the ResourceID fails the projects/.../cryptoKeys/... regex check.

Common situations: GOOGLE_APPLICATION_CREDENTIALS pointing to a missing/invalid JSON file; running in an environment without Application Default Credentials (laptop, CI without Workload Identity); SOPS_GCP_CREDENTIALS set to malformed JSON; mistyped resource path like missing keyRings segment.

Related errors


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