Error message
ssh: handshake failed: knownhosts: key is unknown
Also printed as
- ssh: handshake failed: knownhosts: key mismatch
- ssh: must specify HostKeyCallback
`*knownhosts.KeyError` has a `Want` field: empty for "key is unknown", non-empty for "key mismatch". "ssh: must specify HostKeyCallback" means the `ClientConfig` has no host-key check at all.
golang.org/x/crypto/ssh/knownhosts (Go) — *knownhosts.KeyError from the HostKeyCallback
What it means
The `knownhosts` callback found no entry for this host (and port) in your known_hosts file, so it refused to trust the key the server presented. This is host authentication working: without a known key, the client cannot tell the real server from an impostor. "key mismatch" is the more serious sibling — the host is listed, but with a different key.
Why it happens
The host was never added
commonInteractive OpenSSH asks "Are you sure you want to continue connecting?" and records the key. Go programs do not prompt, so a host that was never added — or a fresh container with an empty known_hosts — fails here.
Wrong host name or port format
commonFor ports other than 22, entries are written as `[host]:port`. A plain `host` entry does not match a connection to port 2222, and an IP address does not match an entry recorded under the DNS name.
The server's key changed (key mismatch)
occasionalReinstalled servers, recycled cloud IPs and load balancers in front of several hosts present new keys. A mismatch can also mean interception, so it must be resolved by checking the new fingerprint, not by deleting the check.
How to fix it
- 1.
Add the host key after verifying it
`ssh-keyscan` only fetches what the network gives you. Compare the fingerprint with a trusted source before adding it; bake verified entries into images or provisioning.
bash # Fetch the host key, then compare its fingerprint with one obtained out of band # (cloud console, provisioning output, the server's /etc/ssh/*.pub). ssh-keyscan -t ed25519 -p 22 server.example.com > /tmp/hostkey ssh-keygen -lf /tmp/hostkey cat /tmp/hostkey >> ~/.ssh/known_hosts # only after the fingerprints match - 2.
Use the bracketed form for custom ports
knownhosts matches host and port exactly as OpenSSH does. `knownhosts.Normalize` and `knownhosts.Line` produce correctly formatted entries from Go.
text # known_hosts entry for a non-default port: brackets and the port are part of the name [server.example.com]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...