getsops/sops · error
GNUPGHOME must be an absolute path
Error message
GNUPGHOME must be an absolute path
What it means
GnuPGHome.Validate requires an absolute path because gpg's GNUPGHOME must be absolute to be unambiguous. If the value is non-empty but relative (e.g. "tmp/gnupg"), validation fails with this message. The home is never used for gpg operations in this state.
Source
Thrown at pgp/keysource.go:196
// Cleanup deletes the GnuPGHome if it passes Validate.
// It returns an error if the GnuPGHome does not pass Validate, or if the
// removal failed.
func (d GnuPGHome) Cleanup() error {
if err := d.Validate(); err != nil {
return err
}
return os.RemoveAll(d.String())
}
// Validate ensures the GnuPGHome is a valid GnuPG home directory path.
// When validation fails, it returns a descriptive reason as error.
func (d GnuPGHome) Validate() error {
if d == "" {
return fmt.Errorf("empty GNUPGHOME path")
}
if !filepath.IsAbs(d.String()) {
return fmt.Errorf("GNUPGHOME must be an absolute path")
}
fi, err := os.Lstat(d.String())
if err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("GNUPGHOME does not exist")
}
return fmt.Errorf("cannot stat GNUPGHOME: %w", err)
}
if !fi.IsDir() {
return fmt.Errorf("GNUGPHOME is not a directory")
}
if perm := fi.Mode().Perm(); perm != 0o700 {
return fmt.Errorf("GNUPGHOME has invalid permissions: got %#o wanted %#o", perm, 0o700)
}
return nil
}
// String returns the GnuPGHome as a string. It does not Validate.View on GitHub (pinned to 13442bb981)
Solutions
- Convert to an absolute path with filepath.Abs before assigning to GnuPGHome.
- Or use pgp.NewGnuPGHome() which always creates an absolute temp directory.
- If the path comes from configuration, validate/normalize it at config-load time.
Example fix
// before
home := pgp.GnuPGHome("gnupg-home")
// after
abs, err := filepath.Abs("gnupg-home")
if err != nil { return err }
home := pgp.GnuPGHome(abs) Defensive patterns
Strategy: validation
Validate before calling
// Go
func absHome(p string) (pgp.GnuPGHome, error) {
abs, err := filepath.Abs(p)
if err != nil { return "", err }
return pgp.GnuPGHome(abs), nil
} Type guard
func absoluteHome(home pgp.GnuPGHome) bool { return filepath.IsAbs(home.String()) } Try / catch
// Go
if err := home.Validate(); err != nil && strings.Contains(err.Error(), "must be an absolute path") {
return fmt.Errorf("normalize GNUPGHOME with filepath.Abs before use: %w", err)
} Prevention
- Normalize any user/config-supplied path with filepath.Abs at load time
- Prefer NewGnuPGHome() which always yields an absolute temp path
- Add a config validator that rejects relative GNUPGHOME values
When it happens
Trigger: Setting GnuPGHome from a user-supplied relative path or a config value without filepath.Abs, then calling Import, ImportContext, Cleanup, or ApplyToMasterKey.
Common situations: Passing a CLI/config argument like './gnupg-home' or 'gnupg' directly into GnuPGHome; composing paths without filepath.Abs in scripts or tests.
Related errors
- cannot import armored key data into GnuPG keyring: %w
- empty GNUPGHOME 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/ed8523addf54e1ed.
Report an issue: GitHub.