Git & CI/CD Intermediate

Resolving ‘Permission denied (publickey)’ Git Errors on macOS: SSH Key Agent Missing

Fix 'Permission denied (publickey)' Git errors on macOS by troubleshooting SSH key agent issues. Learn to add keys and configure your SSH agent for seamless Git operations.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Fix 'Permission denied (publickey)' Git errors on macOS by troubleshooting SSH key agent issues. Learn to add keys and configure your SSH agent for seamless Git operations.

When working with Git on macOS, particularly when interacting with remote repositories (like GitHub, GitLab, or Bitbucket) via SSH, encountering a "Permission denied (publickey)" error can be a frustrating roadblock. This error indicates that your SSH client could not successfully authenticate with the remote Git server using an SSH key. While many factors can contribute to this, a common culprit on macOS is a misconfigured or non-functional SSH key agent, or simply that your private key has not been added to the agent.

This guide will systematically walk you through diagnosing and resolving this issue, focusing on proper SSH agent management and key configuration on your macOS local environment.

Symptom & Error Signature

You will typically observe this error when attempting to perform Git operations that require authentication with a remote server over SSH, such as git clone, git pull, or git push. The command line output will explicitly state "Permission denied (publickey)".

$ git clone [email protected]:youruser/yourrepo.git
Cloning into 'yourrepo'...
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Or, if you attempt to push changes:

$ git push origin main
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.

To further diagnose the SSH connection itself, you might run ssh -T [email protected] (replace github.com with your Git host) and see a similar error:

$ ssh -T [email protected]
[email protected]: Permission denied (publickey).

A verbose SSH debug log (ssh -vvv [email protected]) can offer more insight, potentially showing attempts to use identity files but failing to interact with an agent or not finding suitable keys. If the agent isn't running or keys aren't loaded, you might see output indicating no identities offered via agent.

Root Cause Analysis

The "Permission denied (publickey)" error, specifically when related to the SSH key agent missing on macOS, typically stems from one or more of these underlying issues:

  1. SSH Agent Not Running or Not Exposed: The ssh-agent process, which manages your SSH private keys and handles authentication requests, might not be running, or its environment variables (SSH_AUTH_SOCK, SSH_AGENT_PID) are not correctly set in your current shell session. On macOS, launchd is usually responsible for starting ssh-agent, but shell configurations can interfere.
  2. SSH Key Not Added to Agent: Even if ssh-agent is running, your specific private key (~/.ssh/id_rsa, ~/.ssh/id_ed25519, etc.) has not been loaded into it using ssh-add. The agent cannot use a key it doesn't know about.
  3. Incorrect Key Permissions: SSH requires strict file permissions for private keys (e.g., 600). If permissions are too open, SSH will ignore the key for security reasons.
  4. Misconfigured ~/.ssh/config: Your SSH client configuration file might be missing crucial directives like AddKeysToAgent yes or UseKeychain yes, which enable automatic key loading and persistence via macOS Keychain.
  5. Corrupted or Incorrect Key: Less common, but possible, the private key itself might be corrupted, or the corresponding public key might not be correctly added to your user account on the remote Git service.

The core problem, "SSH key agent missing", usually points to issues 1 and 2, compounded by issue 4 on macOS for persistent solutions.

Step-by-Step Resolution

Follow these steps to diagnose and resolve the SSH key agent issue on your macOS environment.

1. Verify SSH Agent Status and Loaded Keys

First, check if an SSH agent is running and if any keys are currently loaded into it.

ssh-add -l

Expected Outputs:

  • The agent has no identities. (Agent is running, but no keys loaded).
  • A list of loaded keys (e.g., 2048 SHA256:... /Users/youruser/.ssh/id_rsa (RSA)).
  • Could not open a connection to your authentication agent. (Agent is not running or SSH_AUTH_SOCK environment variable is not set).

If you see "Could not open a connection…", proceed to step 2. If you see "The agent has no identities.", proceed to step 3. If keys are listed but you still get the error, check key permissions (Step 4) and remote host configuration (Step 5).

2. Start the SSH Agent and Expose it to Your Shell

If the SSH agent is not running or your shell cannot connect to it, you need to start it and set the necessary environment variables.

The eval "$(ssh-agent -s)" command starts a new ssh-agent process and exports SSH_AUTH_SOCK and SSH_AGENT_PID variables to your current shell session. This is a temporary solution; the agent will persist, but these variables are only set for the current shell and any child processes. For a persistent solution, especially on macOS, see Step 3.

eval "$(ssh-agent -s)"

You should see output similar to:

Agent pid 12345

Now, re-run ssh-add -l. It should now report "The agent has no identities." or list existing keys if launchd was handling it.

3. Add Your SSH Private Key to the Agent

With the agent running, you need to add your private key to it.

ssh-add ~/.ssh/id_rsa
# Or for ED25519 keys:
# ssh-add ~/.ssh/id_ed25519
  • If your key is protected by a passphrase, you will be prompted to enter it.
  • If you have multiple keys, repeat ssh-add for each one, specifying the correct path (e.g., ssh-add ~/.ssh/my_github_key).

After adding the key, verify it's loaded:

ssh-add -l

You should now see your key listed.

By default, keys added via ssh-add are typically only valid for the lifetime of the ssh-agent process. On macOS, you can integrate this with Keychain Access for persistent storage of passphrases.

4. Configure SSH Agent Persistence with macOS Keychain

For a robust and convenient solution on macOS, configure your ~/.ssh/config file to automatically load keys into the agent and store their passphrases in the macOS Keychain. This prevents needing to run ssh-add and enter passphrases after every reboot or new shell session.

First, ensure your ~/.ssh directory and ~/.ssh/config file have the correct, secure permissions.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/config # If it exists, or will be created

Now, create or edit the ~/.ssh/config file:

nano ~/.ssh/config
# Or use your preferred text editor

Add the following lines to the ~/.ssh/config file:

Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_rsa
  # Add other IdentityFile directives if you use multiple keys, e.g.:
  # IdentityFile ~/.ssh/id_ed25519
  • Host *: Applies these settings to all SSH connections. You can create more specific Host blocks if needed.
  • AddKeysToAgent yes: Instructs the SSH client to automatically add identities to the authentication agent if they are not already loaded.
  • UseKeychain yes: (macOS specific) When a passphrase is required, ssh-add will store it in your macOS Keychain. This means you only enter your passphrase once per system unlock/login.
  • IdentityFile ~/.ssh/id_rsa: Explicitly tells SSH which private key file(s) to use. This can prevent SSH from trying every possible key, potentially speeding up connections and improving security.

If you've been using eval "$(ssh-agent -s)" extensively, you might have multiple ssh-agent processes running. To ensure the new configuration takes effect properly, it's best to restart your terminal or even reboot your machine. Alternatively, you can attempt to kill existing ssh-agent processes: killall ssh-agent Then, open a new terminal window. The ssh-agent should be launched automatically by launchd and integrate with your ~/.ssh/config.

The first time you try to connect after setting UseKeychain yes, you'll be prompted for your passphrase. macOS will then ask if you want to allow ssh-add to store this in your keychain. Grant permission for future seamless authentication.

5. Ensure Correct SSH Key File Permissions

SSH is very particular about file permissions for private keys. If they are too open, SSH will ignore them.

chmod 600 ~/.ssh/id_rsa
# Ensure the public key is readable but not writable by others
chmod 644 ~/.ssh/id_rsa.pub
# Ensure the .ssh directory itself has restricted permissions
chmod 700 ~/.ssh

A private key (id_rsa, id_ed25519) must have 600 permissions (read/write only by owner). A public key (id_rsa.pub, id_ed25519.pub) should have 644 permissions (read by owner, group, others; write only by owner). The ~/.ssh directory should have 700 permissions (read/write/execute only by owner).

6. Verify Public Key on Remote Git Host

Confirm that the corresponding public key (~/.ssh/id_rsa.pub or ~/.ssh/id_ed25519.pub) has been correctly added to your user account on the remote Git service (GitHub, GitLab, Bitbucket, etc.).

  • GitHub: Go to Settings -> SSH and GPG keys.
  • GitLab: Go to User Settings -> SSH Keys.
  • Bitbucket: Go to Personal settings -> SSH keys.

If your key is missing or incorrect, copy the content of your public key file:

cat ~/.ssh/id_rsa.pub
# Or
cat ~/.ssh/id_ed25519.pub

And paste it into the appropriate section on your Git hosting provider.

7. Test SSH Connection

After performing the above steps, open a new terminal window to ensure environment variables are refreshed and test your SSH connection.

ssh -T [email protected]
# Replace github.com with your Git hosting provider if different

Expected Successful Output (e.g., for GitHub):

Hi youruser! You've successfully authenticated, but GitHub does not provide shell access.

If you receive this message, your SSH key and agent are configured correctly for Git operations. You can now proceed with your git clone, git push, or git pull commands.

If the error persists, re-run ssh -vvv [email protected] and carefully examine the verbose output for clues, paying close attention to lines related to identity files and authentication attempts. This output often points directly to the remaining issue.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.