git-ecosystem/git-credential-manager · error · Exception
GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your…
Error message
GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your profile.
See {Constants.HelpUrls.GcmCredentialStores} for more information. What it means
When using the '{gpg}' (pass) credential store on a non-desktop (headless) POSIX session, GCM needs a TTY for GPG pinentry. It throws this Exception if neither GPG_TTY nor SSH_TTY is set in the environment and there is no desktop session, because GPG would otherwise be unable to prompt for the passphrase.
Solutions
- Add `export GPG_TTY=$(tty)` to the shell profile or the job's environment before invoking git.
- For non-interactive contexts, set GPG_TTY explicitly (e.g. GPG_TTY=$(tty) || true) and use loopback pinentry with a passphrase file via GCM options.
- Run gpg-agent with a cached passphrase so pinentry is never required in headless jobs.
Example fix
// before (CI step)
- run: git push
// after
- run: |
export GPG_TTY=$(tty)
git push Defensive patterns
Strategy: validation
Validate before calling
if (!process.env.GPG_TTY && !process.env.SSH_TTY && !process.env.DISPLAY && usingGpgStore) {
process.env.GPG_TTY = execSync('tty').toString().trim();
} Prevention
- Always `export GPG_TTY=$(tty)` in profiles used on headless hosts
- Use gpg-agent passphrase caching for non-interactive jobs
- Prefer desktop sessions or loopback pinentry with a passphrase file in CI
When it happens
Trigger: store=gpg with IsDesktopSession=false and no GPG_TTY/SSH_TTY variable — e.g. SSH into a server (without -t / agent forwarding env), cron/systemd jobs, or containers running git operations.
Common situations: Cron jobs or systemd timers performing git fetch/push with pass; CI containers using GPG-encrypted credential files; SSH non-interactive sessions missing tty export.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Cannot use the ' ' credential backing store without a…
- Can only use the ' ' credential store on POSIX systems. See…
- GPG executable does not exist with path
- Failed to start gpg.
- Bitbucket DC OAuth Client ID must be defined
AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11).
Data as JSON: /api/errors/a08246e46b7e9598.
Report an issue: GitHub.
Appendix: source
Thrown at src/Core/CredentialStore.cs:295
{
var message = $"Can only use the '{StoreNames.Gpg}' credential store on POSIX systems.";
_context.Trace2.WriteError(message);
throw new Exception(message + Environment.NewLine +
$"See {Constants.HelpUrls.GcmCredentialStores} for more information."
);
}
execPath = GetGpgPath();
// If we are in a headless environment, and don't have the GPG_TTY or SSH_TTY
// variables set, then error - we need a TTY device path for pin-entry to work headless.
if (!_context.SessionManager.IsDesktopSession &&
!_context.Environment.Variables.ContainsKey("GPG_TTY") &&
!_context.Environment.Variables.ContainsKey("SSH_TTY"))
{
var message = "GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your profile.";
_context.Trace2.WriteError(message);
throw new Exception(message + Environment.NewLine +
$"See {Constants.HelpUrls.GcmCredentialStores} for more information."
);
}
// Check for a redirected pass store location
if (!_context.Settings.TryGetSetting(
GpgPassCredentialStore.PasswordStoreDirEnvar,
Constants.GitConfiguration.Credential.SectionName,
Constants.GitConfiguration.Credential.GpgPassStorePath,
out storeRoot))
{
// Use default store root at ~/.password-store
storeRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".password-store");
}
}
private void ValidateCredentialCache(out string options)View on GitHub (pinned to e8ce762cd0)