rust-lang/cargo · error · anyhow::Error

error: failed to validate host key: {:#}

Error message

error: failed to validate host key:
{:#}

What it means

A catch-all from `certificate_check` for `KnownHostError::CheckError(e)` — a low-level failure during SSH host-key validation (e.g. libgit2/git2 returned an error parsing keys, a malformed known_hosts entry, or an I/O error reading the known_hosts file). The `{:#}` formatting surfaces the underlying error chain.

Source

Thrown at src/sources/git/known_hosts.rs:176

) -> CargoResult<CertificateCheckStatus> {
    let Some(host_key) = cert.as_hostkey() else {
        // Return passthrough for TLS X509 certificates to use whatever validation
        // was done in git2.
        return Ok(CertificateCheckStatus::CertificatePassthrough);
    };
    // If a nonstandard port is in use, check for that first.
    // The fallback to check without a port is handled in the HostKeyNotFound handler.
    let host_maybe_port = match port {
        Some(port) if port != 22 => format!("[{host}]:{port}"),
        _ => host.to_string(),
    };
    // The error message must be constructed as a string to pass through the libgit2 C API.
    match check_ssh_known_hosts(gctx, host_key, &host_maybe_port, config_known_hosts) {
        Ok(()) => {
            return Ok(CertificateCheckStatus::CertificateOk);
        }
        Err(KnownHostError::CheckError(e)) => {
            anyhow::bail!("error: failed to validate host key:\n{:#}", e)
        }
        Err(KnownHostError::HostKeyNotFound {
            hostname,
            key_type,
            remote_host_key,
            remote_fingerprint,
            other_hosts,
        }) => {
            // Try checking without the port.
            if port.is_some()
                && !matches!(port, Some(22))
                && check_ssh_known_hosts(gctx, host_key, host, config_known_hosts).is_ok()
            {
                return Ok(CertificateCheckStatus::CertificateOk);
            }
            let key_type_short_name = key_type.short_name();
            let key_type_name = key_type.name();
            let known_hosts_location = user_known_host_location_to_add(diagnostic_home_config);

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Inspect the formatted `{:#}` error text for the root cause (parse error, permission denied, etc.).
  2. Fix permissions/ownership of `~/.ssh/known_hosts` (e.g. `chmod 644`).
  3. Remove malformed lines from `~/.ssh/known_hosts` or regenerate it.
  4. Bypass Cargo's SSH handling by setting `net.git-fetch-with-cli = true` to use the system `git` CLI.

Example fix

# before: malformed ~/.ssh/known_hosts
# after (in .cargo/config.toml)
[net]
git-fetch-with-cli = true
Defensive patterns

Strategy: try-catch

Validate before calling

# Pre-flight: ensure known_hosts is readable and well-formed:
test -r ~/.ssh/known_hosts || echo 'known_hosts unreadable'
ssh-keygen -l -f ~/.ssh/known_hosts >/dev/null 2>&1 || echo 'known_hosts parse error'

Try / catch

// Wrap cargo git operations and fall back to the CLI on SSH errors:
let out = std::process::Command::new("cargo").args(["fetch"]).output()?;
if !out.status.success() {
    let s = String::from_utf8_lossy(&out.stderr);
    if s.contains("failed to validate host key") {
        // fall back to system git which may handle the SSH config
        std::process::Command::new("git")
            .args(["config", "--global", "credential.helper", "store"]).status()?;
    }
}

Prevention

When it happens

Trigger: Any `KnownHostError::CheckError` returned by `check_ssh_known_hosts` during a git-over-SSH fetch: unreadable `~/.ssh/known_hosts`, a malformed host-key line, unsupported key type, or a git2 internal error. Reached via the git2 certificate-check callback.

Common situations: Corrupted `~/.ssh/known_hosts`; permission errors on the known_hosts file; a key type Cargo's bundled known_hosts logic doesn't parse; SSH library version mismatch; filesystem errors.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/f66964e36e237465.json. Report an issue: GitHub.