Errorgit

Permission denied (publickey)

Why SSH git pushes fail with Permission denied (publickey), how to see which key is actually being offered, and how to add or load the right one.

Last updated

Errorgit
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.

What it means: The git server rejected your SSH connection because it couldn't authenticate any key you offered — either no usable key was sent, or the server doesn't have your public key on file for this account or repo.

Likely causes

Most probable first — with how to confirm.

  • 1.No SSH key is loaded in your local agent, or the wrong one is being offered — run `ssh -vT git@github.com` (or the equivalent for GitLab/Bitbucket). The `-v` is the part that matters: it prints an "Offering public key" line for each identity tried, which is how you see whether the right key was ever presented.
  • 2.Your public key was never added to your account on the git host, or it was added to a different account than the one with access to this repo.
  • 3.You're using the SSH remote URL (`git@github.com:...`) without SSH actually being set up — check `git remote -v`; the HTTPS URL sidesteps SSH entirely.
  • 4.The key exists locally but has overly open file permissions, and SSH refuses to use a private key file that's group- or world-readable — check with `ls -l ~/.ssh/id_ed25519`.

Fixes

Safest first; destructive ones are called out.

  • →Run `ssh -vT git@github.com` — plain `ssh -T` only prints the greeting or the same refusal, while `-v` shows each key offered and the authentications still available. Diagnoses the problem without changing anything.
  • →Add your public key (`~/.ssh/id_ed25519.pub` or `id_rsa.pub`) to the git host's SSH keys settings if it isn't there yet; generate one with `ssh-keygen -t ed25519` if you don't have one at all.
  • →Start the SSH agent and load the key if it exists but isn't active: `eval "$(ssh-agent -s)"` then `ssh-add ~/.ssh/id_ed25519`.
  • →As a quick workaround, switch the remote to HTTPS — `git remote set-url origin https://github.com/user/repo.git` — and authenticate with a token instead of SSH.

Part by part

git@github.com
The SSH user and host. Every GitHub SSH URL authenticates as the user git — your identity comes from the key, not from this name.
Permission denied
The server rejected the connection. It reached GitHub and was refused, which rules out network and DNS problems entirely.
(publickey)
The authentication methods that were tried and failed. Only publickey is listed because that is all GitHub accepts over SSH.

Common mistakes

  • ssh -T git@github.com

    The usual first check, and it does not show which key was offered — so a success here with a failure elsewhere tells you very little. Add -v to see the keys tried and the reason each was rejected.

    ssh -vT git@github.com
  • chmod 777 ~/.ssh/id_ed25519

    SSH refuses to use a private key that is readable by other users, so loosening permissions guarantees failure rather than fixing it. Private keys want 600, and the .ssh directory 700.

  • Generating a new key and starting over

    Works, and usually was not necessary — the common causes are a key not added to the agent, or a key not registered with the account. Both are quicker to check than a fresh key is to create and register.

Questions

How do I see which key is actually being offered?

ssh -vT git@github.com prints each key it tries and how the server responded. That output distinguishes "no key offered" from "key offered and rejected", which are different problems with different fixes.

Do I need ssh-agent?

For a passphrase-protected key, effectively yes, or you will be prompted on every operation. ssh-add loads it, and on macOS --apple-use-keychain persists it across restarts.

Why does it work for one account but not another?

SSH offers keys by convention, not by repository. With several accounts you need a Host block in ~/.ssh/config mapping an alias to a specific IdentityFile, and then to use that alias in the remote URL.

Should I use HTTPS instead?

It is a reasonable alternative, using a token rather than a key. Neither is more secure in practice; SSH avoids token expiry, HTTPS avoids key management. Pick whichever your team already supports well.

Related in Errors