Fixing the 'gpg failed to sign the data' Error in Git

intermediate📦 Git2026-03-31| Linux (Ubuntu/Debian/Arch), macOS (Sonoma/Ventura), Windows (WSL2/Git Bash)

Error Message

error: gpg failed to sign the data fatal: failed to write commit object
#git#gpg#devops#security

The 2 AM Commit Fail

It’s late. You’ve just finished a grueling session squashing a critical bug. You type git commit -m "Fix: resolve race condition" and hit Enter, expecting a success message. Instead, Git throws a brick wall at you:

error: gpg failed to sign the data
fatal: failed to write commit object

This error is frustrating because it’s vague. It rarely means your code is wrong. Usually, it means Git tried to call GPG to sign your work, but GPG couldn't find a way to ask you for your passphrase. It’s a communication breakdown between your terminal and the encryption engine.

Why GPG is Ghosting You

Git doesn't handle the password prompt itself; it hands that job off to an agent. Here is why that handoff usually fails:

  • Missing TTY: GPG doesn't know which terminal screen to use for the password prompt.
  • Stale Agent: The gpg-agent is hanging or crashed in the background.
  • Path Mismatch: You have multiple GPG versions installed, and Git is calling the wrong one.
  • Expired Keys: Your GPG key reached its end-of-life date (commonly 1–2 years after creation).

The "I Need This Pushed Now" Hotfix

If you are in a rush, you can often kickstart the system by manually pointing GPG to your current terminal and restarting the background daemon. Run these three commands:

export GPG_TTY=$(tty)
gpgconf --kill gpg-agent
gpg-agent --daemon

Try your commit again. It should now trigger the popup or terminal prompt for your passphrase. If it works, great—but you’ll likely need the permanent fixes below to stop it from happening again tomorrow.

Permanent Solutions

1. Automate the GPG_TTY Variable

This is the #1 fix for Linux and macOS users. You need to tell your shell to always define the display terminal for GPG. Open your profile configuration (~/.zshrc for Mac/Zsh or ~/.bashrc for Bash) and add this line at the bottom:

export GPG_TTY=$(tty)

Save the file and refresh your session by running source ~/.zshrc.

2. Configure Pinentry for macOS and Linux

GPG uses a small utility called pinentry to show the password box. On macOS, Homebrew often installs this in a location GPG doesn't check by default. You need to be explicit.

Create or edit ~/.gnupg/gpg-agent.conf:

# For Apple Silicon Macs (M1/M2/M3)
pinentry-program /opt/homebrew/bin/pinentry-mac

# For Intel Macs
# pinentry-program /usr/local/bin/pinentry-mac

# For Linux (Server/Headless)
# pinentry-program /usr/bin/pinentry-curses

After saving, restart the agent: gpgconf --kill gpg-agent.

3. Validate Your Key Expiration

Sometimes the configuration is perfect, but the key itself is dead. Check your key status with this command:

gpg --list-secret-keys --keyid-format LONG

Look for a line like sec rsa4096/3AA5C34371567BD2 2022-01-01 [SC] [expired: 2024-01-01]. If you see "expired," you must extend it:

gpg --edit-key 3AA5C34371567BD2
gpg> expire
# Follow the prompts to add 1y or 2y
gpg> save

4. Windows-Specific Fix (Git Bash)

On Windows, Git often bundles its own GPG, which might clash with Gpg4win. Force Git to use the correct version by pointing directly to the executable:

git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe"

Final Verification

Test the pipeline by forcing a signed commit on a dummy change:

git commit -S -m "Testing GPG fix"

Check the results with git log --show-signature -1. If you see gpg: Good signature, your setup is officially repaired. You can now get back to shipping code without the 2 AM headache.

Related Error Notes