{"record":{"id":"94e0dd272672293e","repo":"AutoDarkMode/Windows-Auto-Night-Mode","slug":"failed-to-fetch-sha256-http","errorCode":null,"errorMessage":"Failed to fetch sha256: HTTP {}","messagePattern":"Failed to fetch sha256: HTTP (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"adm-downloader-rs/src/main.rs","lineNumber":162,"sourceCode":"        eprintln!(\"failed to write embedded license HTML to {:?}: {}\", out, e);\r\n        return;\r\n    }\r\n\r\n    // use the Windows shell to open the file with the default application (browser).\r\n    // `start` requires a title argument; pass an empty title string.\r\n    let path_str = out.to_string_lossy().to_string();\r\n    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","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/AutoDarkMode/Windows-Auto-Night-Mode/blob/c15b28e92138a1baff6165bbca80842f06cb819f/adm-downloader-rs/src/main.rs#L144-L180","documentation":"Returned by fetch_expected_sha256 when the HTTP GET for the sidecar checksum file (url + \".sha256\") returns a non-success status. The downloader assumes a SHA256 file exists alongside every release asset. The error is part of the verify step and contributes to exit code ERR_VERIFY (13371).","triggerScenarios":"fetch_expected_sha256(url) builds sha_url = format!(\"{}.sha256\", url) and GETs it. resp.status().is_success() is false — the .sha256 sidecar file is missing or the server errored.","commonSituations":"The release pipeline did not publish a .sha256 sidecar for the asset (404); version mismatch where the asset exists but the checksum file was not uploaded; GitHub rate-limiting (403); proxy/firewall block.","solutions":["Confirm the .sha256 file exists at the expected URL (open url + \".sha256\" in a browser).","Retry to rule out transient GitHub 403/5xx.","If the project stopped shipping sidecar checksums, update verify_sha256 to fetch the hash from the release API/manifest instead.","Check proxy/firewall and network connectivity to github.com.","Pin the downloader to a release version that is known to publish the .sha256 file."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Confirm the .sha256 sidecar exists before the main flow\nfn sha_sidecar_exists(url: &str) -> bool {\n    Client::new().get(&format!(\"{}.sha256\", url)).send().map(|r| r.status().is_success()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"// verify_sha256 -> fetch_expected_sha256 already returns Result mapped to ERR_VERIFY.\n// Retry transient failures and distinguish 404 (permanent) from 5xx (transient):\nlet resp = client.get(&sha_url).send()?;\nif resp.status() == reqwest::StatusCode::NOT_FOUND {\n    anyhow::bail!(\"sha256 sidecar not published for this asset (404)\");\n}\nif !resp.status().is_success() {\n    anyhow::bail!(\"Failed to fetch sha256: HTTP {}\", resp.status());\n}","preventionTips":["Confirm the release publishes a .sha256 sidecar for every asset before shipping the downloader pinned to it.","Distinguish 404 (missing sidecar — permanent) from 403/5xx (transient) in the error path.","Retry transient HTTP failures before bailing.","Consider fetching checksums from the GitHub Releases API as a fallback source."],"tags":["network","http","sha256","checksum","github-release","rust"],"backgroundTag":null,"analyzedSha":"c15b28e92138a1baff6165bbca80842f06cb819f","analyzedAt":"2026-08-13T21:04:56.049Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}