{"record":{"id":"c134f239e8876c3e","repo":"getsops/sops","slug":"cannot-import-armored-key-data-into-gnupg-keyring","errorCode":null,"errorMessage":"cannot import armored key data into GnuPG keyring: %w","messagePattern":"cannot import armored key data into GnuPG keyring: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgp/keysource.go","lineNumber":144,"sourceCode":"\t}\n\treturn GnuPGHome(tmpDir), nil\n}\n\n// Import attempts to import the armored key bytes into the GnuPGHome keyring.\n// It returns an error if the GnuPGHome does not pass Validate, or if the\n// import failed.\n//\n// Consider using ImportContext instead.\nfunc (d GnuPGHome) Import(armoredKey []byte) error {\n\treturn d.ImportContext(context.Background(), armoredKey)\n}\n\n// ImportContext attempts to import the armored key bytes into the GnuPGHome keyring.\n// It returns an error if the GnuPGHome does not pass Validate, or if the\n// import failed.\nfunc (d GnuPGHome) ImportContext(ctx context.Context, armoredKey []byte) error {\n\tif err := d.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"cannot import armored key data into GnuPG keyring: %w\", err)\n\t}\n\n\targs := []string{\"--batch\", \"--import\"}\n\t_, stderr, err := gpgExec(ctx, d.String(), args, bytes.NewReader(armoredKey))\n\tif err != nil {\n\t\tstderrStr := strings.TrimSpace(stderr.String())\n\t\terrStr := err.Error()\n\t\tvar sb strings.Builder\n\t\tsb.WriteString(\"failed to import armored key data into GnuPG keyring\")\n\t\tif len(stderrStr) > 0 {\n\t\t\tif len(errStr) > 0 {\n\t\t\t\tfmt.Fprintf(&sb, \" (%s)\", errStr)\n\t\t\t}\n\t\t\tfmt.Fprintf(&sb, \": %s\", stderrStr)\n\t\t} else if len(errStr) > 0 {\n\t\t\tfmt.Fprintf(&sb, \": %s\", errStr)\n\t\t}\n\t\treturn errors.New(sb.String())","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/pgp/keysource.go#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar home pgp.GnuPGHome\nhome.Import(pubKey) // empty path\n// after\nhome, err := pgp.NewGnuPGHome()\nif err != nil { return err }\nif err := home.Import(pubKey); err != nil { return err }","handlingStrategy":"validation","validationCode":"// Go\nfunc importSafe(home pgp.GnuPGHome, key []byte) error {\n  if err := home.Validate(); err != nil { return err }\n  return home.Import(key)\n}","typeGuard":"func initialized(home pgp.GnuPGHome) bool { return home != \"\" && filepath.IsAbs(home.String()) }","tryCatchPattern":"// Go\nif err := home.Import(armoredKey); err != nil {\n  if strings.Contains(err.Error(), \"cannot import armored key data into GnuPG keyring\") {\n    // recreate home and retry once\n    home, rerr = pgp.NewGnuPGHome(); if rerr != nil { return rerr }\n    return home.Import(armoredKey)\n  }\n  return err\n}","preventionTips":["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"],"tags":["gnupg","pgp","validation","key-import"],"backgroundTag":"gnupg-home-invalid","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}