getsops/sops · error
cannot import armored key data into GnuPG keyring: %w
Error message
cannot import armored key data into GnuPG keyring: %w
What it means
GnuPGHome.ImportContext imports armored key bytes by running `gpg --batch --import` with the home directory set. Before doing so it validates the home path; a failed Validate is wrapped with this message. After validation, a failing gpg execution also produces an import error (the follow-on branch reads stderr), but this exact wrap site fires when the GnuPGHome path itself is invalid.
Source
Thrown at pgp/keysource.go:144
}
return GnuPGHome(tmpDir), nil
}
// Import attempts to import the armored key bytes into the GnuPGHome keyring.
// It returns an error if the GnuPGHome does not pass Validate, or if the
// import failed.
//
// Consider using ImportContext instead.
func (d GnuPGHome) Import(armoredKey []byte) error {
return d.ImportContext(context.Background(), armoredKey)
}
// ImportContext attempts to import the armored key bytes into the GnuPGHome keyring.
// It returns an error if the GnuPGHome does not pass Validate, or if the
// import failed.
func (d GnuPGHome) ImportContext(ctx context.Context, armoredKey []byte) error {
if err := d.Validate(); err != nil {
return fmt.Errorf("cannot import armored key data into GnuPG keyring: %w", err)
}
args := []string{"--batch", "--import"}
_, stderr, err := gpgExec(ctx, d.String(), args, bytes.NewReader(armoredKey))
if err != nil {
stderrStr := strings.TrimSpace(stderr.String())
errStr := err.Error()
var sb strings.Builder
sb.WriteString("failed to import armored key data into GnuPG keyring")
if len(stderrStr) > 0 {
if len(errStr) > 0 {
fmt.Fprintf(&sb, " (%s)", errStr)
}
fmt.Fprintf(&sb, ": %s", stderrStr)
} else if len(errStr) > 0 {
fmt.Fprintf(&sb, ": %s", errStr)
}
return errors.New(sb.String())View on GitHub (pinned to 13442bb981)
Solutions
- Always obtain the GnuPGHome from NewGnuPGHome() and check its error instead of constructing it manually.
- Check the wrapped cause: 'empty GNUPGHOME path', 'must be an absolute path', or 'does not exist', and fix accordingly (initialize or use an absolute existing directory).
- Ensure the home is not cleaned up (Cleanup) before all imports complete.
- Verify the gpg binary exists if validation passes but the import still fails; the wrapped error will show gpg stderr.
Example fix
// before
var home pgp.GnuPGHome
home.Import(pubKey) // empty path
// after
home, err := pgp.NewGnuPGHome()
if err != nil { return err }
if err := home.Import(pubKey); err != nil { return err } Defensive patterns
Strategy: validation
Validate before calling
// Go
func importSafe(home pgp.GnuPGHome, key []byte) error {
if err := home.Validate(); err != nil { return err }
return home.Import(key)
} Type guard
func initialized(home pgp.GnuPGHome) bool { return home != "" && filepath.IsAbs(home.String()) } Try / catch
// Go
if err := home.Import(armoredKey); err != nil {
if strings.Contains(err.Error(), "cannot import armored key data into GnuPG keyring") {
// recreate home and retry once
home, rerr = pgp.NewGnuPGHome(); if rerr != nil { return rerr }
return home.Import(armoredKey)
}
return err
} Prevention
- Always create homes with NewGnuPGHome(); never use the zero value
- Validate() before every Import/Cleanup call
- Do not call Cleanup until all imports for that home are finished
- Ensure the gpg binary is installed and on PATH in the runtime image
When it happens
Trigger: Calling Import (or ImportContext) on a zero-valued GnuPGHome (""), a relative path, a deleted temp dir, or a path that is not a directory - i.e. d.Validate() returns an error before gpg runs.
Common situations: Constructing GnuPGHome{} directly instead of via NewGnuPGHome; calling Cleanup earlier and then reusing the (deleted) home; using a relative path like "gnupg-home"; tests importing into a home that was never initialized.
Related errors
- empty GNUPGHOME path
- GNUPGHOME must be an absolute path
- GNUPGHOME does not exist
- failed to create new GnuPG home: %w
- cannot read armored key data from file: %w
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/c134f239e8876c3e.
Report an issue: GitHub.