Corporate Software
How to fix a git permission denied (publickey) error: a step-by-step guide

Short answer
A git permission denied (publickey) error means Git tried to authenticate to the remote repository over SSH and the server rejected every public key your machine presented. The connection is refused on the server side because either there is no SSH key on your computer at all,
the key was never added to your GitHub/GitLab account, or the right key was never loaded into your SSH agent..
Why a git permission denied (publickey) error happens
SSH authenticates with a key pair instead of a password. A private key stays on your machine, and a public key gets registered with the server or hosting account. When Git connects to a remote using an SSH-style URL such as [email protected]:user/repo.git, the server asks your machine to prove its identity. Your machine offers up whichever keys it has access to, one at a time. If none of those keys match anything the server recognizes, or no key is offered at all, the connection is cut immediately. The [email protected]: Permission denied (publickey) line in your terminal is exactly that rejection.
The most common trigger is running git clone or git push for the first time on a new machine or a fresh server/CI environment. No SSH key pair has ever been generated there, or one was generated but the public half was never registered with GitHub, GitLab, or Bitbucket. A second common cause is that the key exists but ssh-agent was restarted (for example after a reboot) and the key was never re-added to it. A third shows up for developers juggling multiple SSH keys across projects: Git offers its default key first, and if that specific key isn’t registered for this particular repository, the connection gets rejected even though a valid key exists somewhere on disk.
Reading the full error message
The complete error usually looks like this:
[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.
This message actually covers two different possibilities at once: either authentication failed (a key problem) or the repository address or permissions are wrong. In practice the vast majority of cases are a key problem, because a genuinely missing repository usually produces a different SSH-level error. Running ssh -vT [email protected] shows exactly where and with which key the handshake fails; the -v flag prints every key your client attempts, in order.
Common git permission denied (publickey) scenarios
| Scenario | Typical cause | First fix |
|---|---|---|
First git clone on a new machine |
No SSH key has ever been generated | Run ssh-keygen -t ed25519 to create one |
| A key exists but isn’t registered | The public key (.pub) was never added to GitHub/GitLab | Add it under the account’s SSH settings |
ssh-add -l returns an empty list |
The private key was never loaded into ssh-agent | Run ssh-add ~/.ssh/id_ed25519 |
| Multiple projects, multiple keys | Git is trying the wrong key | Set an IdentityFile per host in ~/.ssh/config |
| Inside a CI/CD workflow (e.g. GitHub Actions) | A deploy key or secret is missing or misconfigured | Add the matching SSH private key as a secure secret |
| Your own self-hosted Git server | authorized_keys is missing or has wrong permissions |
.ssh must be 700, authorized_keys must be 600 |
How to fix a git permission denied (publickey) error, step by step
The order below rules out the most common causes first and the more unusual ones last; re-testing the connection after each step tells you exactly which one fixed it.
1. Test authentication independently of Git first
ssh -T [email protected] attempts authentication directly, without touching any repository operation. If the response reads “Hi username! You’ve successfully authenticated,” your key already works and the real problem lies in the repository address or its access permissions. If the response still shows Permission denied (publickey), the issue is definitely on the authentication side, and the following steps apply.
2. Check whether an SSH key actually exists
Run ls -al ~/.ssh and look for id_ed25519/id_ed25519.pub or the older id_rsa/id_rsa.pub files. If none exist, generate a modern key pair with ssh-keygen -t ed25519 -C "[email protected]"; you can add a passphrase or leave it empty. On older systems that don’t support ed25519, pass -t rsa -b 4096 to generate an RSA key instead.
3. Add the public key to your account
Copy the contents of the .pub file (the public key, never the private one) and paste it into the platform’s SSH settings page. On GitHub this lives under Settings → SSH and GPG keys → New SSH key; GitLab and Bitbucket have an equivalent menu. Skipping this step means the server will never recognize your key no matter how valid it is on your own machine. The error simply keeps recurring until the public key is actually registered.
4. Load the private key into ssh-agent
A key sitting on disk isn’t automatically used. ssh-add -l shows which keys are currently loaded into the agent; if the list is empty, or you see “Could not open a connection to your authentication agent,” start the agent first with eval "$(ssh-agent -s)" and then load the key with ssh-add ~/.ssh/id_ed25519. This step may need repeating after every reboot; on macOS, adding UseKeychain yes to ~/.ssh/config removes that recurring hassle.
5. Force the right key when you manage several
Developers who use separate SSH keys for different repositories or accounts need to explicitly tell SSH which key belongs to which host. Adding a block like this to ~/.ssh/config fixes the problem permanently:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
IdentitiesOnly yes
The IdentitiesOnly yes line stops SSH from also offering every other key sitting in the agent, which prevents the server from rejecting several wrong keys in a row and closing the connection entirely.
6. Double-check file permissions
OpenSSH deliberately ignores key files with overly permissive access, for security reasons, and silently skips them. Running chmod 700 ~/.ssh and chmod 600 ~/.ssh/id_ed25519 sets the directory and the private key to the permissions SSH expects. If you’re connecting to your own server, the server-side ~/.ssh/authorized_keys file also needs mode 600, and ~/.ssh needs mode 700, both owned by the user you’re logging in as. Otherwise the server refuses to read the key even when its content is perfectly correct.
Why does this error show up in deploy keys and CI/CD environments?
When GitHub Actions, GitLab CI, or another automation tool tries to reach a repository over SSH, the same error shows up for a different reason: the environment has no SSH key of its own, because a fresh container spins up on every run. The fix is to generate a repository-specific “deploy key,” add it to the repository settings with read-only or read-write access, and store the matching private key in the CI tool’s secure secret storage (for example secrets.DEPLOY_KEY in GitHub Actions). The workflow file then needs to write that secret to ~/.ssh/id_ed25519 at runtime and set its permissions to 600; skip that last step and the exact same permission restriction silently rejects the key again.
The special case of your own self-hosted Git server
Unlike a hosted platform such as GitHub or GitLab, connecting to a Git repository on your own server usually means the root cause is on your side of the connection. In this scenario, the relevant user’s home directory on the server needs a ~/.ssh/authorized_keys file, and the public key you’re connecting with needs to be listed inside it. If the file doesn’t exist, create it; its permissions must be 600, and the parent ~/.ssh directory must be 700. On servers with SELinux enabled, the security context also needs to be correct. If the server logs (/var/log/auth.log or /var/log/secure) show a line like “Authentication refused: bad ownership or modes,” the problem is definitely permissions or ownership, not the key itself.
Common mistakes
The single most common mistake is pasting the contents of the private key instead of the public (.pub) key into the hosting platform’s settings; platforms reject this and return a confusing error. The second common mistake is trying to debug SSH key problems on a repository that was actually cloned over HTTPS; running git remote -v reveals the real protocol, and switching with git remote set-url origin [email protected]:user/repo.git resolves the confusion. The third mistake is running Git commands with sudo. Doing so uses a different user’s home directory, and therefore a different ~/.ssh folder, which makes a perfectly valid key appear to not exist at all.
Checklist
- Did you run
ssh -T [email protected]to test authentication independently of Git? - Does
ls -al ~/.sshconfirm a key pair actually exists? If not, did you generate one withssh-keygen? - Is the public key registered in your account’s SSH settings, and does
ssh-add -lshow the private key loaded in the agent? - If you manage multiple keys, did you set an explicit
IdentityFileper host in~/.ssh/config? - Are
~/.sshand your private key file set to modes 700 and 600, without using sudo?
Next step
A git permission denied (publickey) error looks alarming, but it’s fundamentally a missing authentication step, and the sequence above resolves most cases within minutes. If your team wants a more secure and maintainable approach to SSH key management, developer environments, and CI/CD pipelines, our group company Web Tasarım Ofisi provides end-to-end support for software infrastructure and code management processes.
To bring your version control and automation workflows to a professional standard, explore our custom software service or get in touch with us. Once this error is behind you, a different obstacle you may hit during a push is covered in our guide to fixing a git push rejected error, and day-to-day server and SSH commands are covered in our essential SSH and Linux commands guide.
Sources
- GitHub Docs, Error: Permission denied (publickey), GitHub’s own explanation of the error and its recommended step-by-step fix
Frequently asked questions
What does a git permission denied (publickey) error mean?
It means Git tried to authenticate over SSH and the server rejected every public key your machine offered. The TCP connection itself succeeds, but the authentication step fails, so Git stops the operation entirely.
Why am I still getting this error even though I have an SSH key?
Having a key on disk isn't enough. The public key (the .pub file) needs to be added to your GitHub/GitLab account, the matching private key needs to be loaded into ssh-agent, and the file permissions (700/600) need to be correct. Missing any one of those three conditions gets the key rejected.
Should I use HTTPS or SSH for Git?
HTTPS asks for a username/password or a personal access token and tends to work better behind restrictive firewalls. SSH is key-based, so it never prompts for a password and is usually preferred for automation. Both reach the same repository; the choice is mostly a team preference.
What if I have multiple SSH keys?
By default, Git and SSH try the first suitable key found in ~/.ssh, which may not be the right one when you manage several keys. Adding an explicit IdentityFile entry per host in ~/.ssh/config permanently fixes this.
Can this error happen on my own self-hosted Git server too?
Yes. Unlike GitHub or GitLab, the cause there is usually a missing or incorrectly permissioned authorized_keys file on the server: the ~/.ssh directory needs mode 700, authorized_keys needs mode 600, and both need to be owned by the user you're logging in as.