{"record":{"id":"a08246e46b7e9598","repo":"git-ecosystem/git-credential-manager","slug":"gpg-tty-is-not-set-add-export-gpg-tty-tty-to","errorCode":null,"errorMessage":"GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your profile.\nSee {Constants.HelpUrls.GcmCredentialStores} for more information.","messagePattern":"GPG_TTY is not set; add `export GPG_TTY=\\$\\(tty\\)` to your profile\\.\nSee (.+?) for more information\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Core/CredentialStore.cs","lineNumber":295,"sourceCode":"            {\n                var message = $\"Can only use the '{StoreNames.Gpg}' credential store on POSIX systems.\";\n                _context.Trace2.WriteError(message);\n                throw new Exception(message + Environment.NewLine +\n                                    $\"See {Constants.HelpUrls.GcmCredentialStores} for more information.\"\n                );\n            }\n\n            execPath = GetGpgPath();\n\n            // If we are in a headless environment, and don't have the GPG_TTY or SSH_TTY\n            // variables set, then error - we need a TTY device path for pin-entry to work headless.\n            if (!_context.SessionManager.IsDesktopSession &&\n                !_context.Environment.Variables.ContainsKey(\"GPG_TTY\") &&\n                !_context.Environment.Variables.ContainsKey(\"SSH_TTY\"))\n            {\n                var message = \"GPG_TTY is not set; add `export GPG_TTY=$(tty)` to your profile.\";\n                _context.Trace2.WriteError(message);\n                throw new Exception(message + Environment.NewLine +\n                                    $\"See {Constants.HelpUrls.GcmCredentialStores} for more information.\"\n                );\n            }\n\n            // Check for a redirected pass store location\n            if (!_context.Settings.TryGetSetting(\n                GpgPassCredentialStore.PasswordStoreDirEnvar,\n                Constants.GitConfiguration.Credential.SectionName,\n                Constants.GitConfiguration.Credential.GpgPassStorePath,\n                out storeRoot))\n            {\n                // Use default store root at ~/.password-store\n                storeRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), \".password-store\");\n            }\n\n        }\n\n        private void ValidateCredentialCache(out string options)","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/CredentialStore.cs#L277-L313","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (CI step)\n- run: git push\n// after\n- run: |\n    export GPG_TTY=$(tty)\n    git push","handlingStrategy":"validation","validationCode":"if (!process.env.GPG_TTY && !process.env.SSH_TTY && !process.env.DISPLAY && usingGpgStore) {\n  process.env.GPG_TTY = execSync('tty').toString().trim();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["git-credential-manager","gpg","gpg-tty","headless","environment"],"backgroundTag":"missing-env-var","analyzedSha":"e8ce762cd04b4100ae637b5fbf39ef9d0a96561e","analyzedAt":"2026-09-11T17:15:08.753Z","contentChangedAt":"2026-09-11T17:15:08.753Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}