GitHub / git permission denied (publickey) — how to fix
Quick Answer
# 1. Start ssh-agent and load your key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# 2. Copy your public key — paste it into GitHub / GitLab
cat ~/.ssh/id_ed25519.pub
# GitHub → Settings → SSH and GPG keys → New SSH key
# GitLab → Preferences → SSH Keys → Add new key
# 3. Verify the connection
ssh -T [email protected]
# Expected: Hi <username>! You've successfully authenticated...
When this happens
You run git push, git pull, or git clone over SSH and GitHub shows a publickey error such as:
[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.
Git cannot authenticate because it cannot find or use your SSH private key. This is the common GitHub "permission denied publickey" failure.
What the error means
The SSH connection reached the host but no accepted key was offered
SSH authentication happens before Git can read repository history. GitHub receives one or more public-key offers from your SSH client and accepts a connection only when a matching public key is registered to an account that can access the repository. The error can therefore come from a missing key, an unloaded key, the wrong account, the wrong host alias, or missing repository permission.
Do not regenerate keys immediately. First identify the remote host and the keys your client is actually offering. Replacing a working key can break access to other repositories without fixing the real cause.
Diagnostic sequence
Check the remote, agent, and SSH handshake in that order
The remote URL tells you whether this repository uses SSH at all. The agent listing shows which identities are currently loaded. Verbose SSH output then shows which configuration files and identity files are selected. The diagnostic command does not push code or change the repository.
- An
https://remote does not use SSH keys; it uses HTTPS credentials instead. The agent has no identitiesmeans a key must be loaded withssh-add.Offering public keyin verbose output identifies the key SSH attempted.- A successful GitHub test names the authenticated account, which may reveal that the wrong account is active.
git remote -v
ssh-add -l
ssh -vT [email protected]
Load the intended key
Use a key file that exists and protect its permissions
Private keys must remain on your computer. Register only the matching .pub file with the hosting provider. OpenSSH may ignore a private key that is readable by other users, so keep the ~/.ssh directory and key permissions restrictive.
ls -la ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l
Multiple accounts
Give each GitHub account an explicit SSH host alias
When personal and work accounts use different keys, relying on whichever key the agent offers first is fragile. Define one host alias per account, bind it to a specific identity, and use that alias in the repository remote URL. IdentitiesOnly yes prevents SSH from trying unrelated agent keys first.
# ~/.ssh/config
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
# Repository remote
git remote set-url origin git@github-work:company/repository.git
ssh -T git@github-work
Repository access
Successful SSH authentication does not guarantee repository permission
If ssh -T succeeds but clone, fetch, or push still fails, verify the owner and repository path in git remote -v. Confirm that the authenticated account is a collaborator or organization member and that any organization single sign-on requirement has been authorized for the key. Read access may permit fetch while branch protection or role settings still block push.
Verification
Test authentication, remote reads, then the intended Git operation
Verify one layer at a time. A successful host test confirms the account identity. git ls-remote confirms that account can read this repository without altering it. Only then retry pull or push. This keeps authentication failures separate from later history errors such as non-fast-forward rejection.
ssh -T [email protected]
git ls-remote origin HEAD
git fetch origin
Other causes & fixes
No SSH key exists yet
# Check if you already have a key
ls ~/.ssh/id_*.pub
# If nothing is listed, generate one
ssh-keygen -t ed25519 -C "[email protected]"
macOS: key lost after reboot
On macOS the ssh-agent resets on restart. Add this to ~/.ssh/config to load the key automatically via Keychain:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
Remote URL is HTTPS, not SSH
If the remote URL starts with https://, Git uses a password/token prompt instead of SSH keys.
# Check current URL
git remote -v
# Switch to SSH
git remote set-url origin [email protected]:user/repo.git
Related