{"record":{"id":"8933fe9a55d985d9","repo":"usestrix/strix","slug":"checksum-mismatch-for-filename-expected-sha256","errorCode":null,"errorMessage":"checksum mismatch for {filename}: expected sha256 {expected_digest}, got {actual_digest}","messagePattern":"checksum mismatch for (.+?): expected sha256 (.+?), got (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"strix/interface/update_check.py","lineNumber":311,"sourceCode":"    with tempfile.TemporaryDirectory() as tmp:\n        tmp_dir = Path(tmp)\n        archive_path = tmp_dir / filename\n        console.print(f\"[dim]Downloading[/] {url}\")\n        with requests.get(  # nosec B113\n            url,\n            stream=True,\n            timeout=REQUEST_TIMEOUT_SECONDS * 12,\n        ) as response:\n            response.raise_for_status()\n            with archive_path.open(\"wb\") as f:\n                for chunk in response.iter_content(chunk_size=1 << 20):\n                    f.write(chunk)\n\n        expected_digest = _fetch_asset_digest(version, filename)\n        if expected_digest:\n            actual_digest = _sha256_file(archive_path)\n            if actual_digest != expected_digest:\n                raise RuntimeError(\n                    f\"checksum mismatch for {filename}: \"\n                    f\"expected sha256 {expected_digest}, got {actual_digest}\"\n                )\n        else:\n            console.print(\"[dim yellow]No published checksum available; skipping verification[/]\")\n\n        if is_windows:\n            with zipfile.ZipFile(archive_path) as zf:\n                zf.extract(binary_name, tmp_dir)\n        else:\n            with tarfile.open(archive_path, \"r:gz\") as tf:\n                tf.extract(binary_name, tmp_dir, filter=\"data\")\n\n        new_binary = tmp_dir / binary_name\n        new_binary.chmod(new_binary.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)\n\n        staged = current_exe.with_name(current_exe.name + \".new\")\n        try:","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/interface/update_check.py#L293-L329","documentation":"Raised during self-update (_download_and_replace, update_check.py:311) when the sha256 of the downloaded release archive does not match the digest published for that asset. Strix fetches the expected digest via _fetch_asset_digest(version, filename), hashes the downloaded file with _sha256_file, and treats any mismatch as a corrupt or tampered download, aborting before extraction and binary replacement. If no digest is published, verification is skipped with a warning instead.","triggerScenarios":"Answering 'y' to the update prompt for a binary install while the GitHub release download was truncated or corrupted (network interruption, MITM/proxy rewriting, disk-full during write), or the published checksum file changed mid-release. The temp-dir archive is hashed and compared before any extraction.","commonSituations":"Flaky connection truncating the tarball/zip; corporate proxy or AV stripping/modifying content; a partially-overwritten release asset during publishing; disk-full causing a short write; clock/race when a release was re-uploaded while updating.","solutions":["Re-run the update on a stable network — a clean re-download fixes most truncation cases","Compare manually: download the archive and its checksum asset, run sha256sum, and inspect which side differs","Disable/inspect HTTP-intercepting proxies or AV for github.com release downloads","Ensure temp dir space is sufficient (archive is written to a TemporaryDirectory)","If the published digest itself is wrong (re-uploaded release), wait for maintainers or pin the previous version"],"exampleFix":"# before\n# 'y' at update prompt over flaky wifi -> checksum mismatch\n\n# after\ncurl -LO https://github.com/<repo>/releases/download/vX.Y.Z/strix-X.Y.Z-linux-x86_64.tar.gz\nsha256sum strix-X.Y.Z-linux-x86_64.tar.gz  # verify manually\n# then re-run strix and accept the update on a stable link","handlingStrategy":"retry","validationCode":"expected = _fetch_asset_digest(version, filename)\nif expected:\n    actual = _sha256_file(archive_path)\n    assert actual == expected, \"corrupt download; retry on a stable link\"","typeGuard":"def digest_matches(path, expected: str | None) -> bool:\n    return expected is None or _sha256_file(path) == expected","tryCatchPattern":"for attempt in range(2):\n    try:\n        self_update(console, version=latest)\n        break\n    except RuntimeError as e:\n        if \"checksum mismatch\" in str(e) and attempt == 0:\n            continue  # re-download once: truncation is the usual cause\n        raise","preventionTips":["Update on stable network links; avoid resuming interrupted downloads","Verify large transfers manually with sha256sum when proxies are present","Keep temp dir disk space ample during updates"],"tags":["update","checksum","download","security","integrity"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}