getsops/sops · error
failed to decrypt identity file: %v
Error message
failed to decrypt identity file: %v
What it means
While decrypting an encrypted age identity file, any read/decryption error other than the recognized incorrect-passphrase case is wrapped as "failed to decrypt identity file". This covers I/O errors and malformed ciphertext encountered before identities can be parsed. It signals the identity file could not be turned into plaintext at all.
Source
Thrown at age/encrypted_keys.go:73
return fileKey, nil
}
i.NoMatchWarning()
return nil, age.ErrIncorrectIdentity
}
func (i *EncryptedIdentity) decrypt() error {
d, err := age.Decrypt(bytes.NewReader(i.Contents), &LazyScryptIdentity{i.Passphrase})
if e := new(age.NoIdentityMatchError); errors.As(err, &e) {
// ScryptIdentity returns ErrIncorrectIdentity for an incorrect
// passphrase, which would lead Decrypt to returning "no identity
// matched any recipient". That makes sense in the API, where there
// might be multiple configured ScryptIdentity. Since in cmd/age there
// can be only one, return a better error message.
i.IncorrectPassphrase()
return fmt.Errorf("incorrect passphrase")
}
if err != nil {
return fmt.Errorf("failed to decrypt identity file: %v", err)
}
i.identities, err = age.ParseIdentities(d)
return err
}
// LazyScryptIdentity is an age.Identity that requests a passphrase only if it
// encounters an scrypt stanza. After obtaining a passphrase, it delegates to
// ScryptIdentity.
type LazyScryptIdentity struct {
Passphrase func() (string, error)
}
var _ age.Identity = &LazyScryptIdentity{}
func (i *LazyScryptIdentity) Unwrap(stanzas []*age.Stanza) (fileKey []byte, err error) {
for _, s := range stanzas {
if s.Type == "scrypt" && len(stanzas) != 1 {
return nil, errors.New("an scrypt recipient must be the only one")View on GitHub (pinned to 13442bb981)
Solutions
- Verify the identity file is intact and is a valid age-encrypted (possibly armored) file.
- Re-copy or restore the key file from a backup.
- Update age/SOPS if the file was produced by a newer format version.
Example fix
// before $ head -c 100 key.txt > truncated-key.txt # corrupted key file // after $ age -d -o key.txt key.txt.age # restore full, valid identity file
Defensive patterns
Strategy: validation
Validate before calling
data, err := os.ReadFile(keyPath)
if err != nil {
return err
}
if len(data) == 0 || !bytes.HasPrefix(bytes.TrimSpace(data), []byte("-----BEGIN")) && !isAgeFile(data) {
return fmt.Errorf("%s does not look like an age identity file", keyPath)
} Try / catch
fileKey, err := identity.Unwrap(stanzas)
if err != nil && strings.Contains(err.Error(), "failed to decrypt identity file") {
// restore the key file from backup before retrying
} Prevention
- Checksum key files after download/copy and compare before use
- Store encrypted key files with proper file integrity controls
- Keep backups of age identities
When it happens
Trigger: Calling Unwrap on a LazyScryptIdentity when reading/decrypting the encrypted identity file fails with an unexpected error — corrupted file, truncated download, unsupported armor, or I/O failure.
Common situations: Partially copied or corrupted key files; files encrypted with an incompatible age version; disk/permission errors mid-read.
Related errors
- incorrect passphrase
- failed to read '%s': %w
- failed to copy age decrypted data into bytes.Buffer: %w
- Unknown datatype: %s
- could not read passphrase: %v
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/e6a47c973858e9cc.
Report an issue: GitHub.