{"record":{"id":"54fdeea5e20634ea","repo":"AutoDarkMode/Windows-Auto-Night-Mode","slug":"empty-sha256-file","errorCode":null,"errorMessage":"Empty sha256 file","messagePattern":"Empty sha256 file","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"adm-downloader-rs/src/main.rs","lineNumber":169,"sourceCode":"    if let Err(e) = Command::new(\"cmd\").args([\"/C\", \"start\", \"\", &path_str]).status() {\r\n        eprintln!(\"failed to open license HTML in browser: {}\", e);\r\n    }\r\n}\r\n\r\nfn fetch_expected_sha256(url: &str) -> anyhow::Result<Vec<u8>> {\r\n    // construct URL for the .sha256 file (assume same name + .sha256)\r\n    let sha_url = format!(\"{}.sha256\", url);\r\n    let client = Client::new();\r\n    let resp = client.get(&sha_url).send()?;\r\n    if !resp.status().is_success() {\r\n        anyhow::bail!(\"Failed to fetch sha256: HTTP {}\", resp.status());\r\n    }\r\n    let text = resp.text()?;\r\n    // file should contain the hex hash (optionally followed by filename)\r\n    let hash_str = text\r\n        .split_whitespace()\r\n        .next()\r\n        .ok_or_else(|| anyhow::anyhow!(\"Empty sha256 file\"))?;\r\n    let bytes = Vec::from_hex(hash_str)?;\r\n    Ok(bytes)\r\n}\r\n\r\nfn compute_file_sha256(path: &PathBuf) -> anyhow::Result<Vec<u8>> {\r\n    let mut f = File::open(path)?;\r\n    let mut hasher = Sha256::new();\r\n    let mut buf = [0u8; 8192];\r\n    loop {\r\n        let n = f.read(&mut buf)?;\r\n        if n == 0 {\r\n            break;\r\n        }\r\n        hasher.update(&buf[..n]);\r\n    }\r\n    Ok(hasher.finalize().to_vec())\r\n}\r\n\r","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/AutoDarkMode/Windows-Auto-Night-Mode/blob/c15b28e92138a1baff6165bbca80842f06cb819f/adm-downloader-rs/src/main.rs#L151-L187","documentation":"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.","triggerScenarios":"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\").","commonSituations":"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.","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."],"exampleFix":"// before — only checks for no token\nlet hash_str = text.split_whitespace().next()\n    .ok_or_else(|| anyhow::anyhow!(\"Empty sha256 file\"))?\n\n// after — also validate it is a 64-char hex digest before decoding\nlet hash_str = text.split_whitespace().next()\n    .ok_or_else(|| anyhow::anyhow!(\"Empty sha256 file\"))?\n    .trim();\nif hash_str.len() != 64 || !hash_str.chars().all(|c| c.is_ascii_hexdigit()) {\n    anyhow::bail!(\"sha256 file does not contain a valid 64-char hex digest: {:?}\", hash_str);\n}","handlingStrategy":"validation","validationCode":"// Validate the checksum body shape before trusting it\nfn sha_body_valid(text: &str) -> bool {\n    match text.split_whitespace().next() {\n        Some(t) => t.len() == 64 && t.chars().all(|c| c.is_ascii_hexdigit()),\n        None => false,\n    }\n}","typeGuard":null,"tryCatchPattern":"let hash_str = text.split_whitespace().next()\n    .ok_or_else(|| anyhow::anyhow!(\"Empty sha256 file\"))?;\nif hash_str.len() != 64 || !hash_str.chars().all(|c| c.is_ascii_hexdigit()) {\n    anyhow::bail!(\"sha256 file has invalid digest: {:?}\", hash_str);\n}","preventionTips":["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."],"tags":["sha256","checksum","validation","download","rust"],"backgroundTag":null,"analyzedSha":"c15b28e92138a1baff6165bbca80842f06cb819f","analyzedAt":"2026-08-13T21:04:56.049Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}