SSH disconnects before you can type a password:

Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures
Disconnected from 203.0.113.10 port 22

You have the right key. The server never got to it. SSH offers every identity it can find, in order, and the server counts each one as a failed attempt. Its default limit is six.

Everything below was reproduced against OpenSSH 10.3 on both ends, with a server left at the default MaxAuthTries.

What Is Actually Happening

sshd caps authentication attempts per connection with MaxAuthTries, which defaults to 6:

#MaxAuthTries 6

Each key your client offers burns one attempt, whether or not you meant to use it. With a loaded ssh-agent, an eight-key developer laptop offers eight. If the right key is seventh, the server hangs up before reaching it.

The position of the correct key is the whole problem. Offering the same eleven keys in two different orders gives two different outcomes:

correct key first, then 10 decoys   -> authenticated
10 decoys first, then correct key   -> Too many authentication failures

The cliff is exactly where the default predicts. Testing one decoy count at a time against a server at MaxAuthTries 6:

decoys before the correct key: 3  -> OK
decoys before the correct key: 4  -> OK
decoys before the correct key: 5  -> OK
decoys before the correct key: 6  -> Disconnected
decoys before the correct key: 7  -> Disconnected

The correct key has to land within the first six offers.

GitHub Does Not Do This

A great deal of advice tells you to set IdentitiesOnly because GitHub returns “Too many authentication failures”. It does not.

Offering GitHub twenty unrelated keys produces twenty accepted offers and then a different error:

debug1: Offering public key: .../decoy20 ED25519 SHA256:OWluXSes... explicit
debug1: Authentications that can continue: publickey
git@github.com: Permission denied (publickey).

GitHub is happy to let you try every key you own. If you are looking at Permission denied (publickey) from GitHub, the number of keys is not your problem, and that error has its own causes.

“Too many authentication failures” comes from servers running a stock sshd: your own boxes, a client’s jump host, a VPS. Fix it there.

See Which Keys Are Being Offered

Verbose output lists them in the order they go out:

ssh -v you@your-server 2>&1 | grep -E "Offering|Too many"
debug1: Offering public key: /Users/you/.ssh/id_ed25519_work ED25519 SHA256:... agent
debug1: Offering public key: /Users/you/.ssh/id_ed25519_personal ED25519 SHA256:... agent
debug1: Offering public key: /Users/you/.ssh/id_rsa_old RSA SHA256:... agent

Count them. If the key you need is past the sixth line, that is the failure.

The signature is exact: offering eleven keys to a default server produces six Offering public key lines and then a disconnect. The client had more to try and was not allowed to.

Check what the agent is holding, too:

ssh-add -l

Fix 1: Pin the Key Per Host

The durable fix is to tell SSH exactly which key to use for that host. IdentitiesOnly yes is the part that matters: without it, SSH still offers everything in the agent, and IdentityFile only adds to the list.

Add to ~/.ssh/config:

Host your-server
  HostName your-server.example.com
  User you
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes
chmod 600 ~/.ssh/config
ssh your-server

One key is offered, one attempt is used, and the agent’s other keys are ignored for this host. The same connection that failed above succeeds with the decoys still loaded.

Fix 2: Test It Once From the Command Line

Before editing config, confirm the diagnosis:

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_work you@your-server

If that works and a plain ssh you@your-server does not, the key count was the cause and Fix 1 makes it permanent.

Fix 3: Trim the Agent

Sometimes the right answer is fewer keys, not more configuration:

ssh-add -D          # remove every key from the agent
ssh-add ~/.ssh/id_ed25519_work

This is a per-session fix and the keys come back next time something adds them. Use it to unblock yourself, then write the config entry.

Raising MaxAuthTries Is the Wrong Fix

You will find advice to edit /etc/ssh/sshd_config on the server:

MaxAuthTries 20

That works and it is a bad trade. The limit exists to cut off brute-force attempts, and raising it weakens every account on the host to save one person from a three-line config entry. Fix the client.

Verify

ssh -v your-server 2>&1 | grep -c "Offering public key"
1

One offer means the pin is working. Anything higher means IdentitiesOnly yes is missing, or the Host pattern does not match what you typed.

References