Permission denied (publickey) means SSH could not prove to GitHub that you are who you say you are. GitHub asked for a key, your machine either had none to offer or offered one GitHub does not recognize, so the connection was refused. The fix is to make sure you have an SSH key, that it is loaded into your SSH agent, and that its public half is attached to your GitHub account.
Here is the full error you are probably staring at:
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.Despite the second paragraph, this is almost never about access rights or a missing repository. It is an SSH authentication failure, full stop. Work the checklist below in order and you will land on the broken step.
Why this happens
When your remote URL starts with git@github.com:, Git talks to GitHub over SSH. SSH authenticates you with a key pair: a private key that stays on your machine and a public key you give to GitHub. GitHub never asks for a password on an SSH remote. It only checks: "does this person hold a private key whose public half I have on file?" If the answer is no, you get Permission denied (publickey).
So there are exactly three things that can be wrong, and they map to three checks:
- You do not have an SSH key.
- You have a key, but your SSH agent is not offering it.
- You have a key and the agent is offering it, but GitHub does not have the matching public key on your account.
If you are not even sure you want SSH here, the SSH vs HTTPS remotes comparison lays out the trade-off; switching to an HTTPS remote sidesteps this error entirely. But if you are committed to SSH, keep reading.
Step 1: Do you have an SSH key?
Check what is in your .ssh directory:
ls -al ~/.sshYou are looking for a pair like id_ed25519 (private) and id_ed25519.pub (public), or the older id_rsa / id_rsa.pub. If you see them, skip to Step 2. If the directory does not exist or is empty, you have no key, and that is your problem. Generate one:
ssh-keygen -t ed25519 -C "your_email@example.com"Press Enter to accept the default file location. Set a passphrase if you want one (recommended). This writes ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519.pub. If you want the full cross-platform walkthrough, including the Windows and macOS specifics, I cover how to create an SSH key from scratch in its own guide.
One mistake worth naming: do not run ssh-keygen with sudo. That writes a root-owned key into /root/.ssh that your normal user cannot read, and you will keep hitting the same error wondering why a key you "just made" does nothing. Generating your own key is a user-scoped task. No sudo.
If ssh-keygen is not found, install OpenSSH (it ships by default on macOS and most Linux; on Windows use Git Bash, which bundles it).
Step 2: Is the key loaded into the agent?
The SSH agent holds your private key in memory so SSH can offer it without prompting for the passphrase every time. Start the agent and add your key:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519Confirm the key is loaded:
ssh-add -lThat lists the fingerprints the agent currently holds. If it prints The agent has no identities, your key is not loaded and SSH has nothing to offer GitHub, which produces the exact error you are seeing. Re-run the ssh-add line above.
On macOS, you usually want the agent to load the key automatically and pull the passphrase from the Keychain. Add this to ~/.ssh/config:
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519Then add it to the Keychain once:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519 # macOS Monterey (12) and later
# On older macOS (before 12) use the short form:
ssh-add -K ~/.ssh/id_ed25519Step 3: Is the public key on your GitHub account?
This is the step people skip, and it is the most common cause. Having a key locally does nothing if GitHub has never seen the public half. Print your public key:
cat ~/.ssh/id_ed25519.pubCopy the entire line (it starts with ssh-ed25519 and ends with your email comment). Then in GitHub: Settings, SSH and GPG keys, New SSH key. Paste it, give it a title, and save. I wrote a step-by-step walkthrough of exactly this part with screenshots in how to add an SSH key to GitHub; use it if the GitHub UI bit is where you are stuck.
A subtle trap: if you have several keys, make sure the public key you paste into GitHub matches the private key the agent is offering. Mismatched pairs fail silently with the same Permission denied (publickey) message.
GitLab works the same way: the same .pub file goes into its Settings, SSH Keys panel, and the test command becomes ssh -T git@gitlab.com.
Step 4: Test the connection
Once the key exists, is loaded, and is on GitHub, verify the whole chain with GitHub's test endpoint:
ssh -T git@github.comA working setup answers like this:
Hi username! You've successfully authenticated, but GitHub does not provide shell access.That "does not provide shell access" line is the success message, not an error: GitHub deliberately does not give you a shell. Seeing your username there means authentication works and your git push and git pull over SSH will go through. If you instead get Permission denied (publickey) from this command too, you have isolated the problem to SSH itself (not Git), and one of Steps 1 to 3 is still wrong.
Reading the verbose output
If the test still fails after the checklist, ask SSH to narrate what it is doing:
ssh -vT git@github.comTwo lines tell you most of the story. Watch for the key SSH actually offers:
debug1: Offering public key: /Users/you/.ssh/id_ed25519 ED25519 ...
debug1: Authentications that can continue: publickeyIf you see Offering public key followed by GitHub continuing to ask for publickey, the key being offered is not the one on your account: back to Step 3. If you see no Offering public key line at all, the agent is empty or pointing at a missing file: back to Step 2.
Quick reference
| Symptom | What it means | Fix |
|---|---|---|
~/.ssh is empty | No key exists | ssh-keygen -t ed25519 (Step 1) |
ssh-add -l says no identities | Key not loaded in agent | ssh-add ~/.ssh/id_ed25519 (Step 2) |
| Key offered, GitHub still refuses | Public key not on account, or wrong key | Add the matching .pub to GitHub (Step 3) |
ssh -T works, git push fails | Remote is HTTPS, not SSH | Switch the remote URL to git@github.com:... |
When the wrong remote is the real cause
If ssh -T git@github.com greets you by name but git push still throws the error, your remote is not actually using SSH. Check it:
git remote -vAn HTTPS remote looks like https://github.com/user/repo.git. To use the SSH key you just set up, switch it:
git remote set-url origin git@github.com:user/repo.gitIf there is no remote at all yet, git remote -v prints nothing; in that case you have not wired up the remote, and the path to fix it is to add Git to a project and wire up the remote before any of this SSH troubleshooting applies.
This is also worth knowing because GitHub removed password authentication for HTTPS years ago, which trips people up in a different way; I cover that in the password authentication removed fix. The two errors look unrelated but both come down to "how are you proving who you are."
Where this sits in the bigger picture
Getting SSH working is part of the foundation for everything else: cloning, pushing to a branch with no upstream, and opening your first pull request. If you are early in your Git journey, the Git for beginners guide is the hub that ties these pieces together and points to the rest of the series.
Sources
Authoritative references this article was fact-checked against.
- GitHub Docs: Error: Permission denied (publickey)docs.github.com
- GitHub Docs: Connecting to GitHub with SSHdocs.github.com
- Pro Git: Generating Your SSH Public Keygit-scm.com





