getsops/sops · error
could not encrypt data key with PGP key: %w
Error message
could not encrypt data key with PGP key: %w
What it means
This is the aggregate error returned by EncryptContext after both the go-crypto OpenPGP attempt and the gpg-binary fallback failed. It wraps a multi-error list containing the openpgp error and the 'GnuPG binary error'. Seeing it means sops could not encrypt the data key to this PGP master key by any available method.
Source
Thrown at pgp/keysource.go:295
if !key.disableOpenPGP {
openpgpErr := key.encryptWithOpenPGP(dataKey)
if openpgpErr == nil {
log.WithField("fingerprint", key.Fingerprint).Info("Encryption succeeded")
return nil
}
errs = append(errs, fmt.Errorf("github.com/ProtonMail/go-crypto/openpgp error: %w", openpgpErr))
}
binaryErr := key.encryptWithGnuPG(ctx, dataKey)
if binaryErr == nil {
log.WithField("fingerprint", key.Fingerprint).Info("Encryption succeeded")
return nil
}
errs = append(errs, fmt.Errorf("GnuPG binary error: %w", binaryErr))
log.WithField("fingerprint", key.Fingerprint).Info("Encryption failed")
return fmt.Errorf("could not encrypt data key with PGP key: %w", errs)
}
// encryptWithOpenPGP attempts to encrypt the data key using OpenPGP with the
// PGP key that belongs to Fingerprint. It sets EncryptedDataKey, or returns
// an error.
func (key *MasterKey) encryptWithOpenPGP(dataKey []byte) error {
entity, err := key.retrievePubKey()
if err != nil {
return err
}
encBuf := new(bytes.Buffer)
armorBuf, err := armor.Encode(encBuf, "PGP MESSAGE", nil)
if err != nil {
return err
}
plainBuf, err := openpgp.Encrypt(armorBuf, []*openpgp.Entity{&entity}, nil, &openpgp.FileHints{IsBinary: true}, nil)
if err != nil {View on GitHub (pinned to 13442bb981)
Solutions
- Read both wrapped causes and fix the more specific one (usually 'No public key')
- Import the public key for the fingerprint and verify with gpg --list-keys <fingerprint>
- Confirm the fingerprint in .sops.yaml matches a real key (no typos, no spaces issues)
- Ensure a working gpg binary exists (or SOPS_GPG_EXEC points to it) and GNUPGHOME is valid (0700 dir)
Example fix
// before pgp: 'C6A0...BEEF' # key never imported // after gpg --import team-keys.asc && gpg --list-keys C6A0...BEEF # then re-run sops -e
Defensive patterns
Strategy: try-catch
Validate before calling
fp := fingerprint
for _, args := range [][]string{
{"--homedir", gnupgHome, "--list-keys", fp},
{"--homedir", gnupgHome, "--list-secret-keys", fp},
} {
if out, err := exec.Command("gpg", args...).CombinedOutput(); err != nil {
return fmt.Errorf("key %s unavailable (%v): %s", fp, err, out)
}
} Try / catch
if err := key.EncryptContext(ctx, dataKey); err != nil {
var errs []error
if errors.As(err, &errs) { // aggregate wraps both openpgp and gpg errors
for _, e := range errs { log.Errorf("pgp encrypt: %v", e) }
}
return fmt.Errorf("encrypt to %s failed; run 'gpg --import' and retry: %w", key.Fingerprint, err)
} Prevention
- Pre-flight: verify every .sops.yaml pgp fingerprint exists in the local keyring before encrypting
- Bootstrap fresh environments (laptops, CI) with a key-import step
- Keep gpg installed and SOPS_GPG_EXEC/GNUPGHOME correct
- Handle the wrapped aggregate errors individually to find the root cause
When it happens
Trigger: Calling EncryptContext (directly or via sops encrypt) when the fingerprint is unknown to both the Go keyring and the gpg binary, or both mechanisms fail (bad GNUPGHOME, missing gpg, unusable key).
Common situations: Fresh machine/CI container without imported keys; typo'ed fingerprint in .sops.yaml; gpg not installed; empty injected GnuPGHome.
Related errors
- github.com/ProtonMail/go-crypto/openpgp error: %w
- could not decrypt data key with PGP key: %w
- GnuPG binary error: %w
- failed to encrypt sops data key with pgp: %s
- Could not initialize AES GCM encryption cipher: %s
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/128611111a0dcb28.
Report an issue: GitHub.