Fixing "Host key verification failed"
What Does "Host key verification failed" Mean?
Conclusion: The host key the server presented does not match the one your client remembers, so the connection was aborted. It is not a key or password problem — it stops at verifying the server's identity.
Before SSH authenticates you (by password or public key), it first checks that the server you reached is genuine. It does this with the server's "host key", which is recorded in ~/.ssh/known_hosts the first time you connect. On every later connection, if the presented key does not match the record, SSH aborts. That is Host key verification failed.
Host key verification failed.
The important point: this error has two distinct causes.
- A different key was presented than the one on record (server rebuild, reused IP, rarely a man-in-the-middle attack)
- A first-time host was rejected by strict checking (
StrictHostKeyChecking yesetc.)
The fixes are completely different, so identify which one you have first.
Prerequisites
- Client: Ubuntu / macOS (the concepts are the same)
- Server: OpenSSH server
- What you inspect is mainly the client-side
~/.ssh/known_hosts
How Do You Triage the Cause?
Conclusion: Read the line just above the error.
REMOTE HOST IDENTIFICATION HAS CHANGEDmeans a key mismatch;No ... host key is knownmeans a first-time host was rejected.
The cause is printed on the line right before Host key verification failed.. Scroll up and read it.
Pattern A: the key changed (mismatch with the record)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! ... Offending ECDSA key in /home/user/.ssh/known_hosts:12 ... Host key verification failed.
Pattern B: a first-time host was rejected
No ED25519 host key is known for server.example.com and you have requested strict checking. Host key verification failed.
For Pattern A go to Fixing a changed key; for Pattern B go to First-time connections.
Why Does the Key Change? The Big Picture
Conclusion: Most changes are legitimate server-side events (rebuild, reused IP). A small fraction are man-in-the-middle, so always confirm the change is legitimate before deleting.
| Cause | When it happens | Risk |
|---|---|---|
| Server rebuild / OS reinstall | Host keys were regenerated | Low |
| IP / hostname reassignment | Cloud or DHCP points the name at a new server | Low |
| Host key rotation | Keys updated by operational policy | Low |
| Wrong target | A bastion or port forward led to a different host | Medium |
| Man-in-the-middle (MITM) | An attacker on the path is impersonating it | High |
Most cases are low risk, but when the key changes with no explanation, do not skip verifying before you delete.
Where Is known_hosts and What Does It Record?
Conclusion: Per-user records live in
~/.ssh/known_hosts, system-wide ones in/etc/ssh/ssh_known_hosts. Each line is "host/IP + key type + public key", and the mismatch against it triggers this error.
$ cat ~/.ssh/known_hosts
One line maps to one key for one host.
server.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... [server.example.com]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNh...
Note that non-standard ports are recorded as [hostname]:port. To find the matching entry, use ssh-keygen -F.
$ ssh-keygen -F server.example.com
With HashKnownHosts yes (Ubuntu's default), hostnames are hashed, so you cannot spot the line by eye in cat. But ssh-keygen -R / -F below handle hashed entries correctly, so there is no need to edit the file by hand.
Fixing a Changed Key (ssh-keygen -R)
Conclusion: Remove the entry with
ssh-keygen -R hostname, then reconnect and register the new key. You do not need to openknown_hostsand delete the line manually.
The error prints the file and line number: Offending ... key in /home/user/.ssh/known_hosts:12. Removing that is the fix, but ssh-keygen -R is safer than hand-editing by line number.
$ ssh-keygen -R server.example.com
# Host server.example.com found: line 12 /home/user/.ssh/known_hosts updated. Original contents retained as /home/user/.ssh/known_hosts.old
If you use a non-standard port, match the recorded format.
$ ssh-keygen -R '[server.example.com]:2222'
If you also connect by IP, you must remove both the hostname and the IP entry.
$ ssh-keygen -R 192.0.2.10
After deleting, reconnecting prompts you about the new key. Verify the fingerprint and confirm with yes.
$ ssh user@server.example.com
The authenticity of host 'server.example.com (192.0.2.10)' can't be established. ED25519 key fingerprint is SHA256:abcd1234... Are you sure you want to continue connecting (yes/no/[fingerprint])?
Older guides often hand-edit by line number, but that is error-prone with HashKnownHosts or multiple entries. Prefer ssh-keygen -R.
Before You Delete: Confirm the Change Is Legitimate
Conclusion: If the change is unexpected, compare against the server's real fingerprint before deleting. If they differ, suspect a man-in-the-middle and do not connect over that path.
The whole purpose of Host key verification failed is to detect impersonation. A habit of clearing the warning mechanically disables that protection yourself.
If you can reach the server through another path (console etc.), display the fingerprint of the server's own host key.
$ ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:abcd1234... root@server (ED25519)
If this SHA256:... matches the fingerprint SSH shows on reconnect, the change is legitimate and you can register it safely. If it differs, distrust that connection path.
"Just delete it and reconnect" for an unexpected key change is dangerous — it lets eavesdropping or tampering on the path slip by. Skip the check only when you yourself know about the change event (rebuild, migration, etc.).
First-Time Connections (StrictHostKeyChecking)
Conclusion:
No ... host key is known ... strict checkingmeansStrictHostKeyChecking yesrejected an unknown host. Register the correct key safely; do not loosen it tono.
For a first-time server with strict checking enabled, SSH refuses immediately without an interactive prompt.
No ED25519 host key is known for server.example.com and you have requested strict checking. Host key verification failed.
The fix is to register the correct key in known_hosts. The safest way is to register it after verifying the server's real fingerprint. To allow it just this once, use accept-new.
$ ssh -o StrictHostKeyChecking=accept-new user@server.example.com
accept-new (OpenSSH 7.6+) auto-registers unknown hosts but still rejects a changed key for a known host, unlike no. It automates only first-time registration while keeping impersonation detection.
StrictHostKeyChecking no ignores even a changed key, so do not use it in production. When automation must tolerate unknown hosts, choose accept-new.
Pre-Registering known_hosts (ssh-keyscan)
Conclusion: For automation or fleet rollouts,
ssh-keyscancan fetch keys and add them toknown_hosts— but only when you trust the fetch path itself.
For CI / Ansible where no interactive prompt is possible, register keys before connecting.
$ ssh-keyscan -t ed25519 server.example.com >> ~/.ssh/known_hosts
You can also fetch several hosts at once.
$ ssh-keyscan server1 server2 server3 >> ~/.ssh/known_hosts
ssh-keyscan ingests "whatever key is visible over the network right now". If the path is compromised at fetch time, you register a forged key. Where possible, compare the fetched fingerprint against the known-good value.
Checklist When It Still Fails
Conclusion: Tell A from B by the line above the error — fix A with
ssh-keygen -R, fix B with safe registration. Always verify before deleting and avoid loosening the settings too far.
- [ ] Did you read the line just above
Host key verification failed.(A: change / B: first-time)? - [ ] For Pattern A, did you check the
Offending ... known_hosts:NNfile and line? - [ ] Is the key change expected? (If not, compare fingerprints.)
- [ ] Did you remove it with
ssh-keygen -R hostname(including port form and IP)? - [ ] Did the fingerprint on reconnect match the known-good value?
- [ ] For Pattern B, did you avoid carelessly setting
StrictHostKeyChecking no? (Consideraccept-new.) - [ ] Are there stale entries in the system-wide
/etc/ssh/ssh_known_hosts?