{"record":{"id":"a17aa11c714a6b37","repo":"getsops/sops","slug":"gnupghome-does-not-exist","errorCode":null,"errorMessage":"GNUPGHOME does not exist","messagePattern":"GNUPGHOME does not exist","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgp/keysource.go","lineNumber":201,"sourceCode":"\tif err := d.Validate(); err != nil {\n\t\treturn err\n\t}\n\treturn os.RemoveAll(d.String())\n}\n\n// Validate ensures the GnuPGHome is a valid GnuPG home directory path.\n// When validation fails, it returns a descriptive reason as error.\nfunc (d GnuPGHome) Validate() error {\n\tif d == \"\" {\n\t\treturn fmt.Errorf(\"empty GNUPGHOME path\")\n\t}\n\tif !filepath.IsAbs(d.String()) {\n\t\treturn fmt.Errorf(\"GNUPGHOME must be an absolute path\")\n\t}\n\tfi, err := os.Lstat(d.String())\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"GNUPGHOME does not exist\")\n\t\t}\n\t\treturn fmt.Errorf(\"cannot stat GNUPGHOME: %w\", err)\n\t}\n\tif !fi.IsDir() {\n\t\treturn fmt.Errorf(\"GNUGPHOME is not a directory\")\n\t}\n\tif perm := fi.Mode().Perm(); perm != 0o700 {\n\t\treturn fmt.Errorf(\"GNUPGHOME has invalid permissions: got %#o wanted %#o\", perm, 0o700)\n\t}\n\treturn nil\n}\n\n// String returns the GnuPGHome as a string. It does not Validate.\nfunc (d GnuPGHome) String() string {\n\treturn string(d)\n}\n\n// ApplyToMasterKey configures the GnuPGHome on the provided key if it passes","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/pgp/keysource.go#L183-L219","documentation":"GnuPGHome.Validate uses os.Lstat to check the path; if it does not exist, this error is returned. ImportContext, Cleanup, and ApplyToMasterKey all surface it via their own wrappers. Note Validate allows a nonexistent directory? No - existence is required here (only Lstat success proceeds to the IsDir check), so the home must already exist on disk.","triggerScenarios":"Pointing GnuPGHome at a path that was never created, at a temp directory already removed by Cleanup, or a deleted cache/tmp location, then calling Import/ImportContext, Cleanup, or ApplyToMasterKey.","commonSituations":"Reusing a GnuPGHome after Cleanup succeeded; hardcoding a GNUPGHOME path that was removed; race where another process deleted the temp dir; typo in an absolute path.","solutions":["Create the directory before use (os.MkdirAll(d.String(), 0o700)) or obtain it via NewGnuPGHome().","Do not reuse a GnuPGHome after calling Cleanup; create a fresh one per operation.","Verify the absolute path exists: `ls -ld <path>` and fix the configured value.","If parallel code may delete it, serialize access or check existence with os.Lstat before use."],"exampleFix":"// before\nhome := pgp.GnuPGHome(\"/tmp/stale-gnupg\") // deleted earlier by Cleanup\nhome.Import(key)\n// after\nhome, err := pgp.NewGnuPGHome()\nif err != nil { return err }\ndefer home.Cleanup()","handlingStrategy":"validation","validationCode":"// Go\nfunc ensureExists(home pgp.GnuPGHome) error {\n  if _, err := os.Lstat(home.String()); err != nil {\n    if os.IsNotExist(err) { return os.MkdirAll(home.String(), 0o700) }\n    return err\n  }\n  return nil\n}","typeGuard":"func homeExists(home pgp.GnuPGHome) bool { fi, err := os.Lstat(home.String()); return err == nil && fi.IsDir() }","tryCatchPattern":"// Go\nif err := home.Validate(); err != nil && strings.Contains(err.Error(), \"GNUPGHOME does not exist\") {\n  // recreate the home once\n  nh, nerr := pgp.NewGnuPGHome(); if nerr != nil { return nerr }\n  home = nh\n}","preventionTips":["Treat GnuPGHome as single-use: one lifecycle (create, import, cleanup), never reuse","Create missing directories with os.MkdirAll 0700 before use","Avoid hardcoded /tmp paths that external cleanup jobs may delete","Call Validate() before Import/Cleanup to catch deletion early"],"tags":["gnupg","pgp","validation","filesystem"],"backgroundTag":"gnupg-home-not-found","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}