GPG Error: 'gpg: signing failed: Inappropriate ioctl for device' — Cause, Fix, and Troubleshooting Guide
Fix 'gpg: signing failed: Inappropriate ioctl for device': gpg-agent has no tty to prompt. Set GPG_TTY, use loopback pinentry, or a headless agent.
- #security
- #hardening
- #troubleshooting
- #linux
- #gpg
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
What this error means
GPG needs to unlock your private key, but gpg-agent’s pinentry program has no terminal to prompt on, so it cannot collect the passphrase and the signing operation fails. This is the classic error when signing from a script, CI job, git commit -S inside certain shells, or a remote session without a proper tty.
gpg: signing failed: Inappropriate ioctl for device
gpg: signing failed: No pinentry
error: gpg failed to sign the data
The key material is fine; the problem is entirely about how the agent obtains the passphrase in a non-interactive or tty-less context.
Where it surfaces
git commit -Saborts witherror: gpg failed to sign the data.echo test | gpg --clearsignfails withInappropriate ioctl for device.- Signing works in a normal terminal but not over
sudo su -,cron,tmuxreattach, or CI. gpg --status-fdshows a pinentry launch failure.
Identity and permission causes
GPG_TTYnot set/exported. The agent does not know which tty to attach pinentry to.- Curses pinentry with no tty.
pinentry-cursesneeds a terminal that a script/CI does not provide. - Stale gpg-agent bound to an old terminal after reconnecting a session.
- Non-interactive context. cron/CI genuinely has no tty; the passphrase must be supplied another way.
gitinvoking gpg without a controlling terminal inside GUI tools or hooks.
Tracing the failed authorization
# Is GPG_TTY set to the current terminal?
echo "GPG_TTY=$GPG_TTY"; tty
# Reproduce the bare signing failure
echo test | gpg --clearsign 2>&1 | tail -3
# What pinentry is configured?
grep -i pinentry ~/.gnupg/gpg-agent.conf 2>/dev/null
which pinentry pinentry-curses pinentry-tty 2>/dev/null
If GPG_TTY is empty and tty prints a real device, exporting GPG_TTY usually resolves interactive cases immediately.
Resolution
1. Export GPG_TTY (add to ~/.bashrc/~/.zshrc for persistence):
export GPG_TTY=$(tty)
gpgconf --launch gpg-agent
2. Restart a stale agent after reconnecting a session:
gpgconf --kill gpg-agent
export GPG_TTY=$(tty)
3. For scripts/CI, use loopback pinentry and feed the passphrase from a secret store (never a literal in the file):
# ~/.gnupg/gpg-agent.conf
echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent
echo "$GPG_PASSPHRASE" | gpg --batch --yes --pinentry-mode loopback \
--passphrase-fd 0 --clearsign file.txt
4. Point git at a tty-aware pinentry or set the env in the hook environment:
git config --global gpg.program gpg
# ensure GPG_TTY is exported in the shell that runs git
Hardening access
- Do not hardcode the GPG passphrase in scripts or CI YAML — inject it from a secret manager and pass via
--passphrase-fd. allow-loopback-pinentryweakens the agent’s isolation slightly; enable it only where non-interactive signing is required.- For unattended CI signing, consider a dedicated signing key with a policy-scoped passphrase, rotated regularly.
- A stale agent survives session changes;
gpgconf --kill gpg-agentafter reconnecting avoids confusing tty mismatches.
Related identity errors
- GPG ‘keyserver receive failed’ Error Guide
- GPG Repository Signature Verification Failed Error Guide
- Sudo ‘no tty present and no askpass program specified’ Error Guide
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.