Error message
error: gpg failed to sign the data
Also printed as
- fatal: failed to write commit object
- gpg: skipped "ABCDEF0123456789": No secret key
- gpg: signing failed: No secret key
Git prints gpg's stderr after the first line, for example 'gpg: skipped "<key>": No secret key' or 'gpg: signing failed: Inappropriate ioctl for device'. When `gpg.program` cannot be started, Git prints "(no gpg output)".
What it means
Git asked GnuPG to sign the commit or tag object and gpg exited with an error, so Git aborted ("fatal: failed to write commit object"). Git's own line says nothing about the cause; the gpg lines printed with it (or `[GNUPG:]` status lines) do. The most common one is "No secret key": the configured `user.signingkey` does not exist in this keyring.
Why it happens
The signing key is not in this keyring
common`user.signingkey` copied from another machine, a dotfiles repository, or a CI configuration; the private key was never imported here (`gpg --list-secret-keys` does not show it).
gpg cannot ask for the passphrase
commonWithout `GPG_TTY`, in an IDE, over SSH or in CI there is no terminal or GUI for pinentry. gpg reports "Inappropriate ioctl for device" or a timeout.
The key or signing subkey expired
occasionalgpg refuses to sign with an expired key; the stderr line mentions the expiry, or the key is skipped as unusable.
Git starts the wrong gpg
occasional`gpg.program` pointing at a missing binary or at `gpg` 1.x while the keys live in GnuPG 2's keyring (common on macOS with several installations).
How to fix it
- 1.
Run gpg yourself with the configured key
If `gpg --clearsign` with the same key fails, the problem is GnuPG, not Git — and its message is the real one.
bash git config --get user.signingkey gpg --list-secret-keys --keyid-format=long # is that key listed, with a "sec" line? echo test | gpg --clearsign --local-user "$(git config --get user.signingkey)" > /dev/null && echo "gpg can sign" - 2.
Point Git at an existing key and make pinentry work
Use the long key ID or fingerprint of a secret key that exists locally, set `gpg.program` explicitly, and export `GPG_TTY` in your shell.
bash KEY=$(gpg --list-secret-keys --with-colons alice@example.com | awk -F: '/^sec/ {print $5; exit}') git config --global user.signingkey "$KEY" git config --global gpg.program "$(command -v gpg)" export GPG_TTY=$(tty) # in ~/.bashrc / ~/.zshrc, so pinentry can ask for the passphrase
Related errors
gpg: signing failed: Inappropriate ioctl for deviceGit commit signing with GnuPG 2error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh sign…Git (verify-commit, log --show-signature, merge --verify-signatures) with gpg.format=sshgpg: Can't check signature: No public keyGnuPG (gpg --verify, git verify-commit / verify-tag / log --show-signature)