GPG Signing Failed: Inappropriate Ioctl for Device

gpg: signing failed: Inappropriate ioctl for device usually means GPG cannot reach the terminal it needs to display a passphrase prompt; it does not usually mean the signature or Git commit is invalid. In an interactive Unix-like shell, set GPG_TTY to the current terminal, then confirm that Git can find your secret key and is using the intended GPG executable. This guide walks through the quick fix, key checks, remote environments, and Windows-specific causes.

Use this table to match the rest of the error output to the likely repair.

Symptom Likely Cause What to Do
It fails in an IDE, GUI Git client, SSH session, or container but works in a normal terminal GPG agent cannot find a usable terminal for pinentry Set GPG_TTY inside the environment that runs Git
It fails everywhere, including a normal terminal Missing secret key, unavailable agent, expired key, or incorrect Git configuration List secret keys and set Git’s signing key explicitly
The output includes No secret key Git selected a key that is not in the active GPG home Configure user.signingkey to an available secret key, or restore the intended private key
The output includes lockfile errors, No agent running, or unexpected Windows paths Git is calling the wrong GPG executable or using the wrong GPG home Check gpg.program, GNUPGHOME, and duplicate GPG installations
It works on the host but fails in a dev container or remote machine The container or remote session has separate Git settings, key storage, agent access, or terminal state Configure the signing key and terminal environment inside that environment

What the GPG Ioctl Error Means

An ioctl is an operating-system request used to control a device, including a terminal. “Inappropriate ioctl for device” means GPG or its pinentry program attempted a terminal operation, but the process did not have a usable terminal device.

GPG signing normally requires access to your private key and, in most setups, a passphrase prompt. GPG delegates that prompt to gpg-agent and a pinentry program. If Git was started from an environment with no interactive terminal, or the agent still points to an old terminal, the prompt cannot open and signing fails.

The error is about access to a prompt, not whether Git can create a commit.

This is especially common when you commit through an IDE, an SSH connection without terminal allocation, a container, WSL, a GUI Git client, a hook, or an automated process.

How to Fix GPG Signing Failed: Inappropriate Ioctl for Device

Work through these steps in order. Start in the same shell, container, remote session, or terminal where you plan to run Git.

Step 1: Confirm You Have an Interactive Terminal

  1. Open a regular terminal in the environment where signing fails. For example, open a terminal inside the dev container if the failure occurs there, rather than testing only on the host machine.
  2. On Linux, macOS, WSL, Git Bash, or another Unix-like shell, check whether the shell has a terminal device:
tty

A normal interactive shell prints a terminal path. If it reports that the process is not connected to a terminal, GPG cannot reliably present an interactive passphrase prompt.

  1. Confirm that GPG can see at least one secret key:
gpg --list-secret-keys --keyid-format=long

Look for a sec entry. A pub entry alone is not enough to sign: it represents a public key, while signing requires the private or secret key material.

  1. Run these commands to show whether Git has an explicitly configured signing key and GPG program, including the configuration file that set each value: git config –show-origin –get user.signingkey git config –show-origin –get gpg.program
git config --show-origin --get user.signingkey
git config --show-origin --get gpg.program

The --show-origin output matters because a system, global, repository, or included configuration file can override another setting.

Step 2: Point GPG Agent at the Current Terminal

In Bash, Zsh, and similar shells, export GPG_TTY before making the signed commit:

export GPG_TTY="$(tty)"

Then tell a running GPG agent to update its startup terminal:

gpg-connect-agent updatestartuptty /bye

For Fish shell, set the equivalent exported variable:

set -gx GPG_TTY (tty)

GPG_TTY must describe the terminal available to the process currently running Git. Setting it on your host shell does not automatically fix an IDE, a container, a remote machine, or a GUI app launched separately.

If this resolves the problem in a normal terminal, add the appropriate GPG_TTY assignment to your interactive shell startup file. Do not add it to a noninteractive automation environment that has no terminal.

Step 3: Select a Secret Key Git Can Actually Use

Git may try to sign with your name or email address when no signing key is configured. That can be ambiguous, and it can fail if your secret key uses a different identity or if several keys exist.

  1. Run this command to list the available secret keys and identify the long key ID for the key Git should use: gpg –list-secret-keys –keyid-format=long
gpg --list-secret-keys --keyid-format=long
  1. Set Git’s global signing key to the intended key’s long ID: git config –global user.signingkey YOUR_LONG_KEY_ID Replace YOUR_LONG_KEY_ID with the value shown after the slash on the secret-key line, or use the full fingerprint if that is how your team identifies keys.
git config --global user.signingkey YOUR_LONG_KEY_ID
  1. Run this command to display the signing-key value Git will use: git config –get user.signingkey
git config --get user.signingkey

If you need a different key in one repository, omit --global and run the command from that repository.

If GPG reports No secret key, do not generate a new key just to silence the error unless you truly intend to replace your signing identity. Instead, make the intended private key available in the active GPG home, restore it through your organization’s approved key-recovery process, or configure the remote environment to use your forwarding setup.

Step 4: Make an Intended Signed Commit and Verify It

After setting the terminal and key configuration, make a normal commit containing work you actually want to commit:

git commit -S -m "Describe the staged change"

The -S option explicitly requests a signed commit even if automatic signing is not enabled.

Verify the latest commit’s signature afterward:

git log --show-signature -1

A valid signature confirms that Git invoked GPG, GPG accessed the secret key, and the verification side can locate the corresponding public key.

If signing still fails, rerun the commit only when you have a real staged change ready to commit and want Git’s trace output:

GIT_TRACE=1 git commit -S -m "Describe the staged change"

The trace shows the GPG command Git launches. That makes it easier to spot an unexpected executable, a wrong key argument, or a configuration file you did not realize was active.

Fixing GPG Signing in SSH, Containers, and IDEs

Terminal allocation, a current GPG_TTY, and pinentry access let SSH, containers, and IDE Git processes sign commits.

SSH Sessions Without a Terminal

A remote shell needs terminal allocation if GPG must show an interactive prompt. Connect with terminal allocation when appropriate:

ssh -t USER@HOST

Then, on the remote machine, set GPG_TTY from that session’s tty output before committing.

Do not expect a noninteractive SSH command, scheduled job, or CI runner to answer a passphrase prompt. Those environments need a deliberate signing design, such as an approved CI signing key, a securely configured agent, or a workflow that does not require interactive local-key signing.

Dev Containers and Remote Development Environments

Containers have their own process environment, Git configuration, GPG home, and installed binaries. A signing key configured on the host is not automatically available inside the container.

Inside the container, verify that the signing key exists and reset the terminal variable there:

gpg --list-secret-keys --keyid-format=long
export GPG_TTY="$(tty)"

If your setup forwards a GPG agent from the host, the container must also be configured to reach that agent. A stale GPG_TTY copied from the host is not useful inside the container; it must refer to the container session’s current terminal.

I reproduce this kind of problem one environment at a time in a clean container or virtual environment because it removes machine-specific noise.

IDEs and GUI Git Clients

An IDE’s integrated terminal may work while the IDE’s commit dialog fails. The terminal has a pseudo-terminal; the GUI commit process may not inherit it.

Try a signed commit from the IDE’s integrated terminal after setting GPG_TTY. If that succeeds, configure the IDE to inherit the correct environment or make signed commits from a normal terminal until its Git integration can access pinentry correctly.

Avoid disabling commit signing globally as a permanent “fix.” That only hides the prompt problem and can cause policy failures later when a repository requires verified commits.

Windows: Check for the Wrong GPG Executable

On Windows, Git may invoke a different gpg.exe than the one you installed and configured. This can happen when Git, Gpg4win, Cygwin, MSYS2, WSL, or older tools each provide a GPG executable.

Check GPG executables visible on your PATH:

where.exe gpg.exe
where.exe gpg2.exe

Also inspect Git’s configured override:

git config --show-origin --get gpg.program

GnuPG specifically advises checking for multiple gpg.exe or gpg2.exe installations when Windows Git signing produces lockfile or agent errors. In GnuPG’s documented Windows case, Git was repaired by explicitly setting gpg.program to the installed GnuPG executable:

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

That path is an example from GnuPG’s gpg4win case, not a universal Windows path. Confirm the exact executable in the intended GnuPG installation’s bin directory before setting it.

The reported installation in that case was gpg4win 3.1.16 | GnuPG 2.2.28; treat that as a comparison example rather than a required version. Check the version output from the executable Git actually invokes:

gpgconf --show-versions

Do not mix a Unix-oriented GPG binary with a Windows GPG home unless the environment is designed for it. A binary from WSL, Cygwin, or MSYS2 may not handle Windows paths, agents, and lock files the same way as the GPG installation you expect Git to use.

GPG Home, USB Keys, and Lockfile Errors

When GNUPGHOME Changes Where GPG Looks

GPG normally stores keys and configuration in its default home directory. The GNUPGHOME environment variable can override that location, for example, when keys are stored on a removable drive.

Ask GPG which home directory is active in the current environment:

gpgconf --list-dirs homedir

If Git is launched by an IDE or GUI application, it inherits that application’s environment, not necessarily the environment of the terminal where you tested. Make sure the Git process receives the intended GNUPGHOME value and that the drive containing the key files is mounted and accessible.

When GPG Reports an Invalid Lockfile

A message such as invalid size of lockfile occurs before GPG can use the key. In GnuPG’s documented USB-home case, the failing lockfile was D:\gnupg\pubring.kbx.lock; your relevant lockfile is in the active GNUPGHOME directory named in the error output.

First close Git, IDEs, terminals, and any other processes that could be using that GPG home. Confirm that Git is using the correct GPG executable and that the removable drive or network location is available. Only then consider removing the specific stale lock file named in the error.

Do not delete lock files while another GPG process may still be running. If the lock immediately returns, stop and investigate the selected GPG executable, permissions, removable-media reliability, and concurrent processes instead of repeatedly deleting files.

Confirm the Fix and Keep It Working

A durable setup has all of these pieces aligned:

  • An interactive terminal has GPG_TTY set to its current terminal device.
  • Git’s user.signingkey identifies a secret key available to the active GPG home.
  • Git’s gpg.program, if configured, points to the intended executable.
  • Remote machines and containers have their own explicit GPG, agent, and Git configuration.
  • A normal signed commit can be checked with git log --show-signature -1.

Document the expected signing executable and any required GNUPGHOME or agent-forwarding setup in the repository’s developer documentation. That prevents a host-only configuration from becoming an unexplained failure in containers, CI, or new developer machines.

Frequently Asked Questions

What Does “Inappropriate Ioctl for Device” Mean?

The “Inappropriate ioctl for device” error means GPG attempted to control or query a terminal device, but the process had no usable terminal. For commit signing, the missing terminal usually prevents gpg-agent and pinentry from showing the private-key passphrase prompt. Setting GPG_TTY from an interactive shell often resolves that specific problem.

How Do I Fix gpg: signing failed: No secret key?

Configure Git with a key that appears as a sec entry in the output of gpg --list-secret-keys --keyid-format=long. Set that long key ID or fingerprint with git config --global user.signingkey YOUR_LONG_KEY_ID, then ensure Git is running with the same GPG home that contains the private key.

What Is GPG Signing in Git?

GPG signing attaches a cryptographic signature to a commit or tag using your private key. Other people can verify that signature with your public key to confirm that the commit was signed by the holder of that private key and was not changed afterward.

Why Does GPG Signing Work in My Terminal but Not My IDE?

Your terminal and IDE may use different environments. The terminal may have a valid GPG_TTY, access to an agent socket, and the correct GNUPGHOME, while the IDE’s GUI commit process has none of those inherited settings. Configure the IDE’s environment or use an integrated terminal that has a valid terminal device.

How Do I Fix a General “GPG Check Failed” Error?

First determine whether the failure happened while signing or while verifying. A signing failure usually involves the secret key, passphrase prompt, agent, terminal, or selected executable; a verification failure usually involves a missing public key, trust information, or an invalid signature. Capture the full GPG output rather than relying on Git’s final summary line, then use the relevant GPG configuration path described in GnuPG’s Windows troubleshooting record if Git appears to be launching the wrong program.