Error message
Host key verification failed.
Also printed as
- No ED25519 host key is known for 127.0.0.1 and you have requested strict checking.
- fatal: Could not read from remote repository.
Git prints it followed by "fatal: Could not read from remote repository.". The key type in the preceding line (`ED25519`, `ECDSA`, `RSA`) is the type the server offered.
What it means
ssh could not confirm that the server is the one it claims to be, so it aborted before authentication. Either the host is not in `known_hosts` and ssh could not ask you (batch mode, CI, a Git command without a terminal), or it is listed with a different key. The line before it says which: "No … host key is known for …" for an unknown host, a large "REMOTE HOST IDENTIFICATION HAS CHANGED" warning for a changed one.
Why it happens
First connection without a terminal
commonCI runners, cron jobs, Docker builds and `git` inside scripts start with an empty `known_hosts`. With `BatchMode yes` or no TTY, ssh cannot show the confirmation prompt and fails.
The host's key differs from the recorded one
commonServer reinstalled, IP address reused by another machine, load balancer in front of hosts with different keys — or an interception. See the "REMOTE HOST IDENTIFICATION HAS CHANGED" entry.
The known_hosts file is not the one you think
occasionalA different `HOME` in CI or sudo, `UserKnownHostsFile` pointing elsewhere, or a file owned by another user that ssh cannot read or write.
How to fix it
- 1.
Record the host key after verifying it
`ssh-keyscan` shows what the network gives you; compare its fingerprint with one from a trusted source before trusting it.
bash # Store the server's host key once, after checking its fingerprint out of band. ssh-keyscan -t ed25519 server.example.com > /tmp/hostkey ssh-keygen -lf /tmp/hostkey # compare with the fingerprint from your provider/console cat /tmp/hostkey >> ~/.ssh/known_hosts - 2.
Ship verified known_hosts to CI
Store the verified line as a secret or in the repository. `StrictHostKeyChecking no` or `ssh-keyscan` at run time make the job accept whatever answers.
yaml # GitHub Actions: put the verified known_hosts line into a secret, not ssh-keyscan at run time - name: Configure SSH run: | install -d -m 700 ~/.ssh echo "${{ secrets.DEPLOY_KNOWN_HOSTS }}" > ~/.ssh/known_hosts chmod 600 ~/.ssh/known_hosts - 3.
Use the published keys of Git hosting providers
GitHub, GitLab and Bitbucket publish their host key fingerprints; GitHub also via its meta API.
bash # GitHub publishes its SSH host keys (also at https://api.github.com/meta, "ssh_keys") curl -s https://api.github.com/meta | jq -r '.ssh_keys[] | "github.com " + .' >> ~/.ssh/known_hosts