Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Jenkins By James Joyner IV · · 9 min read

Jenkins Error: 'Host key verification failed. fatal: Could not read from remote repository.' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix Jenkins 'Host key verification failed. fatal: Could not read from remote repository.' on SSH SCM checkout: known_hosts, host key strategy, ssh-keyscan.

  • #jenkins
  • #ci-cd
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

A Jenkins build fails during SCM checkout the moment it opens an SSH connection to your Git server. Git refuses to talk to a host it cannot cryptographically identify, and the checkout aborts before a single object is transferred:

Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

This is not a credentials or permissions problem — your SSH key may be perfectly valid. The failure happens one step earlier: the agent that runs the checkout has never recorded the server’s host key in its known_hosts, or Jenkins’ Git Host Key Verification is set to a strategy that rejects the unknown key. The fix is to establish trust for the server’s host key on the machine (controller or agent) that actually performs the clone.

Symptoms

  • Checkout fails immediately over an ssh:// or git@host:org/repo.git URL; HTTPS URLs for the same repo work.
  • The console log shows Host key verification failed. followed by fatal: Could not read from remote repository.
  • The same clone works when run manually as your own user but fails as the Jenkins agent user.
  • The failure started right after adding a new agent, migrating a job to a different node, or rotating the Git server.
  • No ED25519 host key is known for ... or Host key for server ... does not match appears in the log.
  • Freestyle and Pipeline jobs both fail identically at the SCM step, before any build steps run.

Common Root Causes

  • The agent’s known_hosts has never seen this server — checkout runs on an agent (not the controller), and that agent’s home directory has no entry for the Git host, so SSH treats it as unknown.
  • Git Host Key Verification set to “Known hosts file” with an empty/missing file — the strategy requires a pre-seeded ~/.ssh/known_hosts, but the file does not exist for the Jenkins user.
  • Wrong home directory for the agent process — the agent runs as a service user whose $HOME is / or unset, so ~/.ssh/known_hosts resolves to a path SSH cannot read or write.
  • Host key changed or rotated — the server was rebuilt or its key was regenerated, so the stored key no longer matches and SSH refuses the connection.
  • Key type mismatch — the server offers only an ED25519 key but known_hosts (or ssh-keyscan) only captured the RSA key, or vice versa.
  • Non-standard SSH port not reflected in known_hosts — the entry was scanned for port 22 but the repo URL uses ssh://git@host:2222/....

How to diagnose

First confirm the checkout is over SSH and identify which machine runs it. In a Pipeline, the node executing the checkout/git step is where known_hosts must be correct — usually an agent, not the controller.

Check the effective home and existing known hosts as the Jenkins user on that node:

# Run these on the agent that performs the checkout
whoami
echo "HOME=$HOME"
ls -la "$HOME/.ssh/"
cat "$HOME/.ssh/known_hosts" 2>/dev/null | grep -i git.example.com

Reproduce the exact SSH handshake Git uses, with verbose output:

# Confirms whether the host key is trusted and which key type is offered
ssh -vT -o StrictHostKeyChecking=yes git@git.example.com

Inspect the key the server actually presents so you know what to trust:

# Prints the server's public host keys (all types) for the correct port
ssh-keyscan -p 22 git.example.com

In the Jenkins UI, check the global strategy at Manage Jenkins > Security > Git Host Key Verification Configuration. Note which of the four strategies is selected; it governs how every Git SSH checkout validates host keys. For a single failing job, open the build’s Console Output and confirm the failure is at the SCM checkout stage, before build steps.

Fixes

Fix 1: Seed the agent’s known_hosts and use the “Known hosts file” strategy

This is the most secure production setup. Capture the server key once and pin it, then tell Jenkins to require it.

# As the Jenkins agent user, on each agent that checks out over SSH
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
ssh-keyscan -p 22 git.example.com >> "$HOME/.ssh/known_hosts"
chmod 644 "$HOME/.ssh/known_hosts"

Then in Manage Jenkins > Security > Git Host Key Verification Configuration, select Known hosts file (verifies against ~/.ssh/known_hosts of the user running Jenkins/the agent). Verify the captured fingerprint against your Git provider’s published fingerprints before trusting it.

Fix 2: Accept first connection (trust on first use)

If you cannot pre-seed every agent, choose Accept first connection. Jenkins records the host key on the first checkout and pins it thereafter — connections succeed initially and fail loudly only if the key later changes. This is a reasonable middle ground for internal servers where you control the host.

Fix 3: Provision known_hosts through the Pipeline for ephemeral agents

For containerized or dynamically provisioned agents whose home directory is fresh on every build, establish trust inside the job. Store the expected key in a Jenkins Secret file or config so it is pinned, not blindly scanned:

pipeline {
  agent any
  environment {
    // A Secret file credential containing the vetted host key line(s)
    KNOWN_HOSTS = credentials('git-example-known-hosts')
  }
  stages {
    stage('Checkout') {
      steps {
        sh '''
          mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
          cp "$KNOWN_HOSTS" "$HOME/.ssh/known_hosts"
          chmod 644 "$HOME/.ssh/known_hosts"
        '''
        git url: 'ssh://git@git.example.com:22/org/repo.git',
            branch: 'main',
            credentialsId: '<credentials-id>'
      }
    }
  }
}

Fix 4: Clear a stale/changed host key

If the server was legitimately rebuilt and the key changed, remove the old entry and re-add the current key (after verifying the new fingerprint):

ssh-keygen -R git.example.com                 # remove stale entry
ssh-keyscan git.example.com >> "$HOME/.ssh/known_hosts"

Fix 5 (last resort, non-production): No verification

The No verification strategy disables host key checking entirely. It unblocks a build immediately but removes protection against man-in-the-middle attacks, so treat it as a temporary diagnostic only — never leave it enabled for production credentials.

What to watch out for

  • Fix the agent’s known_hosts, not the controller’s, when checkout runs on an agent — a common time sink is trusting the key on the wrong machine.
  • Confirm the agent process actually has a writable $HOME; service-managed agents often run with HOME=/ and silently fail to read or write ~/.ssh/known_hosts.
  • Scan and pin the correct key type and port — an ED25519-only server plus an RSA-only known_hosts entry still fails verification.
  • Prefer pinning a vetted key over blind ssh-keyscan | >> known_hosts in CI; scanning trusts whatever answers, defeating the point of verification.
  • When rotating Git servers, update known_hosts on every agent before the cutover so builds don’t fail in a wave.
  • If several unrelated jobs break at once, suspect the global strategy in Git Host Key Verification Configuration rather than any single repo.
Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.