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
- Open the .sha256 URL in a browser and confirm it contains a 64-char hex digest.
- If the published file is genuinely empty, flag it upstream and pin to a release with a valid checksum.
- Retry once to rule out a transient empty-body response from a CDN.
- Inspect whether a proxy is rewriting/stripping response bodies.
- 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
- Validate the sidecar contains a 64-char hex digest, not just non-empty.
- Retry once to rule out a transient empty body from a CDN.
- Flag empty/invalid checksum files upstream so the release pipeline is fixed.
- Check whether a proxy is stripping response bodies.
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
- sha256 mismatch: expected {:x?}, got {:x?}
- Failed to fetch sha256: HTTP {}
- Failed to download: HTTP {}
- Auto start task could not be set.
AI-assisted analysis of AutoDarkMode/Windows-Auto-Night-Mode@c15b28e921 (2026-08-13).
Data as JSON: /api/errors/54fdeea5e20634ea.
Report an issue: GitHub.