{"record":{"id":"10deaf0b35063486","repo":"getsops/sops","slug":"failed-to-encrypt-sops-data-key-with-gcp-kms-key","errorCode":null,"errorMessage":"failed to encrypt sops data key with GCP KMS key: %w","messagePattern":"failed to encrypt sops data key with GCP KMS key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gcpkms/keysource.go","lineNumber":189,"sourceCode":"\tservice, err := key.newKMSClient(ctx)\n\tif err != nil {\n\t\tlog.WithField(\"resourceID\", key.ResourceID).Info(\"Encryption failed\")\n\t\treturn fmt.Errorf(\"cannot create GCP KMS service: %w\", err)\n\t}\n\tdefer func() {\n\t\tif err := service.Close(); err != nil {\n\t\t\tlog.Error(\"failed to close GCP KMS client connection\")\n\t\t}\n\t}()\n\n\treq := &kmspb.EncryptRequest{\n\t\tName:      key.ResourceID,\n\t\tPlaintext: dataKey,\n\t}\n\tresp, err := service.Encrypt(ctx, req)\n\tif err != nil {\n\t\tlog.WithField(\"resourceID\", key.ResourceID).Info(\"Encryption failed\")\n\t\treturn fmt.Errorf(\"failed to encrypt sops data key with GCP KMS key: %w\", err)\n\t}\n\t// NB: base64 encoding is for compatibility with SOPS <=3.8.x.\n\t// The previous GCP KMS client used to work with base64 encoded\n\t// strings.\n\tkey.EncryptedKey = base64.StdEncoding.EncodeToString(resp.Ciphertext)\n\tlog.WithField(\"resourceID\", key.ResourceID).Info(\"Encryption succeeded\")\n\treturn nil\n}\n\n// SetEncryptedDataKey sets the encrypted data key for this master key.\nfunc (key *MasterKey) SetEncryptedDataKey(enc []byte) {\n\tkey.EncryptedKey = string(enc)\n}\n\n// EncryptedDataKey returns the encrypted data key this master key holds.\nfunc (key *MasterKey) EncryptedDataKey() []byte {\n\treturn []byte(key.EncryptedKey)\n}","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/gcpkms/keysource.go#L171-L207","documentation":"The GCP KMS client was created successfully, but the kms.Encrypt RPC for the SOPS data key failed. SOPS wraps the Google API error, which typically indicates IAM permission, key state, or project/location mismatch issues.","triggerScenarios":"service.Encrypt(ctx, req) returns a non-nil error during MasterKey.EncryptContext — e.g. the caller lacks roles/cloudkms.cryptoKeyEncrypter on the key, the key is disabled/destroyed, or the resource ID names a nonexistent key.","commonSituations":"Service account missing cloudkms.cryptoKeyEncrypter/get; key scheduled for destruction; typo in cryptoKey name; regional key accessed from wrong location; quota or transient 5xx from Google API.","solutions":["Read the wrapped Google API status: if 403, grant roles/cloudkms.cryptoKeyEncrypter to the identity.","Verify the key exists and is ENABLED via `gcloud kms keys describe`.","Check the ResourceID region/location matches the actual key location.","For transient 5xx/429 errors, retry with backoff."],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"// Pre-check IAM: gcloud kms keys describe KEY --location L --keyring R --project P\n// and confirm the identity has roles/cloudkms.cryptoKeyEncrypter and key state ENABLED.","typeGuard":"null","tryCatchPattern":"if err := key.EncryptContext(ctx, dataKey); err != nil {\n    var apiErr *apierror.APIError\n    if errors.As(err.Unwrap(), &apiErr) && apiErr.Code() == 5 {\n        // retry with backoff for transient failures\n    }\n    return err\n}","preventionTips":["Grant roles/cloudkms.cryptoKeyEncrypter to the encrypting identity.","Monitor key state; alert before scheduled destruction.","Pin ResourceIDs in .sops.yaml and review them in code review."],"tags":["gcp","kms","encryption","iam"],"backgroundTag":"kms-encrypt-denied","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}