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

Empty sha256 file

Error message

Empty sha256 file

What it means

Returned by fetch_expected_sha256 when the .sha256 file was fetched successfully (HTTP 2xx) but its text content contains no parseable token — text.split_whitespace().next() returns None. This means the checksum file exists but is empty or whitespace-only, so there is no hex hash to compare against.

Source

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

    if let Err(e) = Command::new("cmd").args(["/C", "start", "", &path_str]).status() {
        eprintln!("failed to open license HTML in browser: {}", e);
    }
}

fn fetch_expected_sha256(url: &str) -> anyhow::Result<Vec<u8>> {
    // construct URL for the .sha256 file (assume same name + .sha256)
    let sha_url = format!("{}.sha256", url);
    let client = Client::new();
    let resp = client.get(&sha_url).send()?;
    if !resp.status().is_success() {
        anyhow::bail!("Failed to fetch sha256: HTTP {}", resp.status());
    }
    let text = resp.text()?;
    // file should contain the hex hash (optionally followed by filename)
    let hash_str = text
        .split_whitespace()
        .next()
        .ok_or_else(|| anyhow::anyhow!("Empty sha256 file"))?;
    let bytes = Vec::from_hex(hash_str)?;
    Ok(bytes)
}

fn compute_file_sha256(path: &PathBuf) -> anyhow::Result<Vec<u8>> {
    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())
}

View on GitHub (pinned to c15b28e921)

Solutions

  1. Open the .sha256 URL in a browser and confirm it contains a 64-char hex digest.
  2. If the published file is genuinely empty, flag it upstream and pin to a release with a valid checksum.
  3. Retry once to rule out a transient empty-body response from a CDN.
  4. Inspect whether a proxy is rewriting/stripping response bodies.
  5. Add a length/format pre-check: bail early with a clearer message if the token is not 64 hex chars.

Example fix

// before — only checks for no token
let hash_str = text.split_whitespace().next()
    .ok_or_else(|| anyhow::anyhow!("Empty sha256 file"))?

// after — also validate it is a 64-char hex digest before decoding
let hash_str = text.split_whitespace().next()
    .ok_or_else(|| anyhow::anyhow!("Empty sha256 file"))?
    .trim();
if hash_str.len() != 64 || !hash_str.chars().all(|c| c.is_ascii_hexdigit()) {
    anyhow::bail!("sha256 file does not contain a valid 64-char hex digest: {:?}", hash_str);
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the checksum body shape before trusting it
fn sha_body_valid(text: &str) -> bool {
    match text.split_whitespace().next() {
        Some(t) => t.len() == 64 && t.chars().all(|c| c.is_ascii_hexdigit()),
        None => false,
    }
}

Try / catch

let hash_str = text.split_whitespace().next()
    .ok_or_else(|| anyhow::anyhow!("Empty sha256 file"))?;
if hash_str.len() != 64 || !hash_str.chars().all(|c| c.is_ascii_hexdigit()) {
    anyhow::bail!("sha256 file has invalid digest: {:?}", hash_str);
}

Prevention

When it happens

Trigger: fetch_expected_sha256: resp is success, text = resp.text(), but text.split_whitespace().next() is None (empty or all-whitespace body). ok_or_else produces anyhow!("Empty sha256 file").

Common situations: The release pipeline uploaded an empty .sha256 file; a CDN/cache served an empty body; a man-in-the-middle/proxy stripped the body; a copy/paste error in the release artifacts; the file contains only a newline.

Related errors


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