rust-lang/cargo · error
failed to verify the checksum of
Error message
failed to verify the checksum of `{}` What it means
After downloading a `.crate` tarball from a registry, Cargo computes `SHA256(data)` and compares it to the checksum recorded in the registry index / lockfile. A mismatch means the downloaded bytes differ from what the registry attests — indicating corruption, a man-in-the-middle, a stale mirror, or a tampered cache. The error names the package id that failed.
Solutions
- Clear the cached tarball: `cargo cache --autoclean` or remove `~/.cargo/registry/cache/<index>/<pkg>-<ver>.crate`, then re-run.
- Re-fetch the index: `rm -rf ~/.cargo/registry/index/<index>` and `cargo fetch`, to rule out a stale index.
- Switch off or update the registry mirror/proxy that may be serving a mismatched tarball.
- Verify network integrity (retry on a stable connection, disable aggressive VPN/proxy caching).
Example fix
# before: download corrupted/mismatched $ cargo build error: failed to verify the checksum of `serde v1.0.0` # after: clear and refetch $ rm -rf ~/.cargo/registry/cache/index.crates.io-*/serde-1.0.0.crate $ cargo fetch && cargo build
Defensive patterns
Strategy: retry
Validate before calling
// Before trusting a downloaded tarball, recompute and compare.
fn verify_crate_sha256(path: &Path, expected: &str) -> Result<(), anyhow::Error> {
let data = std::fs::read(path)?;
use sha2::{Digest, Sha256};
let mut h = Sha256::new(); h.update(&data);
let got = hex::encode(h.finalize());
if got != expected { anyhow::bail!("checksum mismatch for {}: got {}", path.display(), got); }
Ok(())
} Type guard
fn checksum_matches(path: &std::path::Path, expected: &str) -> bool {
std::fs::read(path).ok().map(|d| {
use sha2::{Digest, Sha256}; let mut h = Sha256::new(); h.update(&d);
hex::encode(h.finalize()) == expected
}).unwrap_or(false)
} Try / catch
for attempt in 0..3 {
match registry.finish_download(...) {
Ok(f) => return Ok(f),
Err(e) if e.to_string().contains("checksum") && attempt < 2 => {
let _ = std::fs::remove_file(&crate_path); // retry after clearing
continue;
}
Err(e) => return Err(e),
}
} Prevention
- Keep `~/.cargo/registry/cache` on reliable storage.
- Use trustworthy registries / mirrors with consistent index+crate state.
- In CI, cache the registry but verify checksums on restore.
- Avoid interrupting Cargo mid-download.
When it happens
Trigger: `finish_download` in `src/sources/registry/download.rs` is called after the HTTP fetch completes; the computed SHA-256 of `data` does not equal the `checksum` argument passed in. Triggered by truncated downloads, proxy corruption, disk errors, registry mirror skew, or an out-of-date index pointing at a replaced tarball.
Common situations: Flaky network/proxy truncating the tarball; a corporate mirror whose cached `.crate` was replaced but whose index was not updated; concurrent processes writing into `~/.cargo/registry/cache`; disk/full-filesystem partial writes; clock-skewed or partially-synced registry mirrors.
Related errors
- failed to verify the checksum of
- invalid tarball downloaded, contains a file at
- invalid tarball downloaded, contains an entry at
- path ` ` is not a blob in the git repo
- cache expected 4 bytes for index schema version
AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11).
Data as JSON: /api/errors/8f8e92b95703d662.
Report an issue: GitHub.
Appendix: source
Thrown at src/sources/registry/download.rs:102
})
}
/// Verifies the integrity of `data` with `checksum` and persists it under the
/// directory at `cache_path`.
///
/// This is primarily called by [`RegistryData::finish_download`](super::RegistryData::finish_download).
pub(super) fn finish_download(
cache_path: &Filesystem,
gctx: &GlobalContext,
encoded_registry_name: InternedString,
pkg: PackageId,
checksum: &str,
data: &[u8],
) -> CargoResult<File> {
// Verify what we just downloaded
let actual = Sha256::new().update(data).finish_hex();
if actual != checksum {
anyhow::bail!("failed to verify the checksum of `{}`", pkg)
}
gctx.deferred_global_last_use()?.mark_registry_crate_used(
global_cache_tracker::RegistryCrate {
encoded_registry_name,
crate_filename: pkg.tarball_name().into(),
size: data.len() as u64,
},
);
cache_path.create_dir()?;
let path = cache_path.join(&pkg.tarball_name());
let path = gctx.assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path);
let mut dst = OpenOptions::new()
.create(true)
.read(true)
.write(true)
.open(&path)
.with_context(|| format!("failed to open `{}`", path.display()))?;View on GitHub (pinned to eb98b54bc9)