git-ecosystem/git-credential-manager · error · Trace2Exception
Failed to decrypt file
Error message
Failed to decrypt file '{0}' with gpg. exit={1}, out={2}, err={3} What it means
After gpg runs during DecryptFile, a non-zero exit code means decryption failed. The library captures stdout/stderr, formats them into this message, and throws Trace2Exception — so the exception text contains the gpg exit code and gpg's own diagnostic output explaining why decryption failed.
Solutions
- Read the exception message's err= portion for gpg's actual reason (e.g. 'No secret key').
- Import the correct secret key: gpg --import <keyfile>, and verify with gpg --list-secret-keys.
- Re-encrypt the file for a key available in this environment, or copy the keyring from the original machine.
- Confirm the file is a valid GPG-encrypted file (file <path>) and not corrupted; restore from backup if needed.
Defensive patterns
Strategy: try-catch
Validate before calling
// before decrypting, check the file is plausibly GPG data byte[] head = File.ReadAllBytes(path)[..4]; bool looksGpg = head[0] == 0x85 || head[0] == 0x80; // OpenPGP packet tags
Try / catch
try { plaintext = gpg.DecryptFile(path); }
catch (Trace2Exception ex) when (ex.Message.StartsWith("Failed to decrypt file"))
{ // parse err= from ex.Message; e.g. 'No secret key' -> instruct key import
throw new InvalidOperationException("Decryption failed; ensure the correct secret key is imported into the keyring.", ex); } Prevention
- Ensure the encrypting key's secret half exists in the target environment's keyring.
- Re-encrypt credential files when moving machines or rotating keys.
- Verify file integrity (non-zero size, GPG header) before decrypting.
When it happens
Trigger: DecryptFile invoked on a file that gpg cannot decrypt: wrong/missing secret key, corrupted or non-GPG file, bad passphrase, untrusted key, or wrong recipient.
Common situations: Credentials file encrypted with a key not present in the current keyring (new machine, regenerated keys); file re-encrypted for a different recipient; truncated downloads.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- Cannot use the ' ' credential backing store without a…
- Can only use the ' ' credential store on POSIX systems. See…
- GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your…
- GPG executable does not exist with path
- helper error ( )
AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11).
Data as JSON: /api/errors/b93216227b21695c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Core/Gpg.cs:60
PrepareEnvironment(psi);
using (var gpg = _processManager.CreateProcess(psi))
{
if (!gpg.Start(Trace2ProcessClass.Other))
{
throw new Trace2Exception(_trace2, "Failed to start gpg.");
}
gpg.WaitForExit();
if (gpg.ExitCode != 0)
{
string stdout = gpg.StandardOutput.ReadToEnd();
string stderr = gpg.StandardError.ReadToEnd();
var format = "Failed to decrypt file '{0}' with gpg. exit={1}, out={2}, err={3}";
var message = string.Format(format, path, gpg.ExitCode, stdout, stderr);
throw new Trace2Exception(_trace2, message, format);
}
return gpg.StandardOutput.ReadToEnd();
}
}
public void EncryptFile(string path, string gpgId, string contents)
{
var psi = new ProcessStartInfo(_gpgPath, $"--encrypt --batch --recipient \"{gpgId}\" --output \"{path}\"")
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true, // Ok to redirect stderr for non-git-related processes
};
PrepareEnvironment(psi);
View on GitHub (pinned to e8ce762cd0)