rust-lang/cargo · error

failed to verify the checksum of

Error message

failed to verify the checksum of `{}`

What it means

For a local registry, instead of downloading, Cargo reads the `.crate` file from disk and computes its SHA-256 to compare against the checksum recorded in the index. A mismatch means the on-disk tarball differs from what the index attests — corruption, manual edit, or a desync between index and crate files. Mirrors error 146 but for the local (no-network) path.

Solutions

  1. Re-sync the entire local registry (both `index/` and crate files) from a trusted source.
  2. Remove the offending `.crate` file and re-vendor it so index and crate match.
  3. Verify integrity with `sha256sum <crate>` and compare to the index entry.
  4. Rebuild the local registry with a tool that computes checksums consistently (e.g. `cargo vendor`).

Example fix

# before: crate file on disk mismatches index
$ cargo build --registry mylocal
error: failed to verify the checksum of `serde v1.0.0`

# after: re-vendor the matching crate
$ sha256sum /srv/cargo-registry/<dep>/serde-1.0.0.crate   # compare to index
$ cargo vendor /srv/cargo-registry                       # rebuild consistently
Defensive patterns

Strategy: validation

Validate before calling

fn verify_local_crate_sha256(crate_path: &Path, expected: &str) -> Result<(), anyhow::Error> {
    let data = std::fs::read(crate_path)?;
    use sha2::{Digest, Sha256}; let mut h = Sha256::new(); h.update(&data);
    if hex::encode(h.finalize()) != expected {
        anyhow::bail!("local crate checksum mismatch: {}", crate_path.display());
    }
    Ok(())
}

Type guard

fn local_crate_checksum_ok(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

if actual != checksum {
    // re-sync crate file from the trusted source before failing hard
    resync_local_registry(&self.root)?;
    return self.download(pkg, checksum); // one retry
}

Prevention

When it happens

Trigger: `LocalRegistry::download()` computes `Sha256(crate_file)` and it does not equal the `checksum` from the index. Happens when the local `.crate` file was modified, partially written, truncated, or replaced out-of-band with the index left stale.

Common situations: Manual replacement of a `.crate` file without updating the index; rsync/copy interrupted leaving a partial file; disk corruption; the local registry was rebuilt but an old crate file was left behind; mismatched index/crate pairs after a partial sync.

Related errors


AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11). Data as JSON: /api/errors/1819945c439fb753. Report an issue: GitHub.

Appendix: source

Thrown at src/sources/registry/local.rs:196

        let path = self.root.join(&pkg.tarball_name()).into_path_unlocked();
        let mut crate_file = paths::open(&path)?;

        // If we've already got an unpacked version of this crate, then skip the
        // checksum below as it is in theory already verified.
        let dst = path.file_stem().unwrap();
        if self.src_path.join(dst).into_path_unlocked().exists() {
            return Ok(MaybeLock::Ready(crate_file));
        }

        if !self.quiet {
            self.gctx.shell().status("Unpacking", pkg)?;
        }

        // We don't actually need to download anything per-se, we just need to
        // verify the checksum matches the .crate file itself.
        let actual = Sha256::new().update_file(&crate_file)?.finish_hex();
        if actual != checksum {
            anyhow::bail!("failed to verify the checksum of `{}`", pkg)
        }

        crate_file.seek(SeekFrom::Start(0))?;

        Ok(MaybeLock::Ready(crate_file))
    }

    async fn finish_download(
        &self,
        _pkg: PackageId,
        _checksum: &str,
        _data: &[u8],
    ) -> CargoResult<File> {
        panic!("this source doesn't download")
    }
}

View on GitHub (pinned to eb98b54bc9)