AutoDarkMode/Windows-Auto-Night-Mode · critical · anyhow::Error

sha256 mismatch: expected {:x?}, got {:x?}

Error message

sha256 mismatch: expected {:x?}, got {:x?}

What it means

Returned by verify_sha256 when the SHA-256 of the downloaded installer file does not equal the expected hash fetched from the .sha256 sidecar. On mismatch the downloaded file is deleted (remove_file) and the error is bailed, contributing to exit code ERR_VERIFY (13371). This is the integrity check that guards against corrupted or tampered downloads.

Source

Thrown at adm-downloader-rs/src/main.rs:193

    let mut f = File::open(path)?;
    let mut hasher = Sha256::new();
    let mut buf = [0u8; 8192];
    loop {
        let n = f.read(&mut buf)?;
        if n == 0 {
            break;
        }
        hasher.update(&buf[..n]);
    }
    Ok(hasher.finalize().to_vec())
}

fn verify_sha256(url: &str, path: &PathBuf) -> anyhow::Result<()> {
    let expected = fetch_expected_sha256(url)?;
    let actual = compute_file_sha256(path)?;
    if expected != actual {
        let _ = remove_file(path);
        anyhow::bail!(
            "sha256 mismatch: expected {:x?}, got {:x?}",
            expected,
            actual
        );
    }
    Ok(())
}

/// run the main download/verify/install flow. The installer's exit code (if run)
/// is written into `installer_code`. On failure this returns one of the
/// explicit error codes (ERR_DOWNLOAD, ERR_VERIFY, ERR_INSTALL_SPAWN).
fn run_install_flow(
    url: &str,
    temp_path: &PathBuf,
    installer_code: &mut Option<i32>,
) -> Result<(), i32> {
    // download
    if let Err(e) = download_file(url, temp_path) {

View on GitHub (pinned to c15b28e921)

Solutions

  1. Re-download from a clean network path (no proxy/AV interference) and re-verify.
  2. Confirm the asset URL and the .sha256 URL reference the exact same release/build.
  3. Temporarily disable AV real-time scanning of the temp directory during download+verify.
  4. If the mismatch persists across retries, treat the release as compromised and pin to a known-good version.
  5. Compare the printed expected vs. got hashes against the project's published checksums manually.
Defensive patterns

Strategy: validation

Validate before calling

// (Defense is the check itself.) Re-verify after a clean re-download:
fn reverify(url: &str, path: &PathBuf) -> anyhow::Result<()> {
    let expected = fetch_expected_sha256(url)?;
    let actual = compute_file_sha256(path)?;
    if expected != actual { anyhow::bail!("sha256 mismatch"); }
    Ok(())
}

Try / catch

// run_install_flow maps verify failures to ERR_VERIFY. On mismatch the file
// is already deleted; surface a clear message and allow a fresh re-download:
if let Err(e) = verify_sha256(url, temp_path) {
    eprintln!("verify failed: {}", e);
    // optionally retry the whole download once before returning ERR_VERIFY
    return Err(ERR_VERIFY);
}

Prevention

When it happens

Trigger: verify_sha256(url, path): fetch_expected_sha256(url) returns expected bytes; compute_file_sha256(path) hashes the downloaded file in 8KB chunks; expected != actual triggers the bail at line 193 and remove_file.

Common situations: The download was truncated or corrupted by a network error/proxy; the .sha256 file corresponds to a different version/build than the asset URL; a MITM or compromised mirror altered the installer; antivirus modified the EXE after write; disk corruption; the hardcoded base URL and the checksum file drifted out of sync after a re-release.

Related errors


AI-assisted analysis of AutoDarkMode/Windows-Auto-Night-Mode@c15b28e921 (2026-08-13). Data as JSON: /api/errors/f62db4f615e2f124. Report an issue: GitHub.