Skip to content
Latchkey

GPG_TTY and the Inappropriate ioctl Error

GPG_TTY points gpg-agent at the current terminal so pinentry can prompt; in CI there is no terminal, so you bypass it.

The classic "Inappropriate ioctl for device" failure comes from gpg trying to read a passphrase with no terminal. Interactively you fix it with GPG_TTY; in CI you skip the prompt entirely.

What it does

GnuPG 2.x delegates passphrase entry to gpg-agent, which launches a pinentry program on a terminal. GPG_TTY tells the agent which terminal that is. When unset (or wrong), pinentry cannot attach and signing fails with an ioctl error.

Common usage

Terminal
# interactive shells: export the current tty
export GPG_TTY=$(tty)
# CI: there is no tty, so do not rely on GPG_TTY at all
gpg --batch --pinentry-mode loopback \
  --passphrase-fd 0 --detach-sign file.tar.gz

Options

SettingWhat it does
GPG_TTY=$(tty)Tell gpg-agent the controlling terminal (interactive)
--pinentry-mode loopbackBypass pinentry; gpg handles the passphrase (CI)
--passphrase-fd <n>Feed the passphrase without a terminal
pinentry-mode loopback (gpg.conf)Make loopback the default in config

In CI

GPG_TTY only helps when a real terminal exists. On a runner there is none, so do not chase GPG_TTY; instead disable the prompt with --pinentry-mode loopback and supply the passphrase via --passphrase-fd. The ioctl error is a symptom of an attempted prompt, not of a missing GPG_TTY per se.

Common errors in CI

"gpg: signing failed: Inappropriate ioctl for device" is the headline symptom: gpg-agent tried to open pinentry on a terminal that does not exist. The CI fix is --pinentry-mode loopback plus a supplied passphrase, not setting GPG_TTY. "No pinentry" or "No such file or directory" means no pinentry program is installed at all.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →