{"record":{"id":"a896816735f1f4fd","repo":"rust-lang/rust","slug":"hash-mismatch-for-package-path-sha1-vs-sha1","errorCode":null,"errorMessage":"hash mismatch for package {path}: {sha1} vs {sha1_known} (known good)","messagePattern":"hash mismatch for package (.+?): (.+?) vs (.+?) \\(known good\\)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"src/ci/docker/scripts/android-sdk-manager.py","lineNumber":56,"sourceCode":"\nclass Package:\n    def __init__(self, path, url, sha1, deps=None):\n        if deps is None:\n            deps = []\n        self.path = path.strip()\n        self.url = url.strip()\n        self.sha1 = sha1.strip()\n        self.deps = deps\n\n    def download(self, base_url):\n        _, file = tempfile.mkstemp()\n        url = base_url + self.url\n        subprocess.run([\"curl\", \"-o\", file, url], check=True)\n        # Ensure there are no hash mismatches\n        with open(file, \"rb\") as f:\n            sha1 = hashlib.sha1(f.read()).hexdigest()\n            if sha1 != self.sha1:\n                raise RuntimeError(\n                    \"hash mismatch for package \"\n                    + self.path\n                    + \": \"\n                    + sha1\n                    + \" vs \"\n                    + self.sha1\n                    + \" (known good)\"\n                )\n        return file\n\n    def __repr__(self):\n        return \"<Package \" + self.path + \" at \" + self.url + \" (sha1=\" + self.sha1 + \")\"\n\n\ndef fetch_url(url):\n    page = urllib.request.urlopen(url)\n    return page.read()\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/rust-lang/rust/blob/7088e4b63a9516ebfbfe2ab2d999cf01a528ac14/src/ci/docker/scripts/android-sdk-manager.py#L38-L74","documentation":"Raised by Package.download() in android-sdk-manager.py at line 56 when the SHA-1 hash of the downloaded file does not match the expected (pinned) sha1 stored in the Package object. This is a tamper/integrity check for Android SDK packages. The lockfile pins each package's URL and sha1; if the downloaded content differs, the script aborts to prevent using a corrupted or compromised package.","triggerScenarios":"Package.download(base_url) fetches the file via curl at line 51, reads it, computes hashlib.sha1 at line 54, and compares at line 55. If sha1 != self.sha1, RuntimeError is raised at line 56. The expected sha1 comes from the lockfile (path/url/sha1 per line) or from the Google repository XML.","commonSituations":"A mirrored package on the rust-lang-ci-mirrors S3 bucket was corrupted or replaced; the Google repository updated a package but the lockfile still pins the old sha1; a network/proxy issue corrupted the download; or the mirror bucket content is stale.","solutions":["Re-download the package (delete the temp file / cached copy and retry).","If the mirror is stale or corrupted, update the lockfile by re-running 'android-sdk-manager.py add-to-lockfile' with the package name to get the current sha1 from Google's repository, then 'update-mirror' to push a fresh copy.","Verify network/proxy integrity (run curl manually and compare sha1).","If the Google-side package legitimately changed, update the lockfile sha1 to match the new known-good hash after verifying the source."],"exampleFix":"# before: lockfile pins stale sha1\n# packages-lock.txt\nsdk-tools-linux;4333796.zip <url> <old-sha1>\n# after: regenerate lockfile\npython3 android-sdk-manager.py add-to-lockfile packages-lock.txt 'sdk-tools-linux;4333796'","handlingStrategy":"validation","validationCode":"# Before relying on a downloaded package, verify its hash\nimport hashlib\ndef verify_sha1(filepath, expected_sha1):\n    with open(filepath, 'rb') as f:\n        actual = hashlib.sha1(f.read()).hexdigest()\n    if actual != expected_sha1:\n        print(f'Hash mismatch: {actual} vs expected {expected_sha1}')\n        return False\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    path = package.download(base_url)\nexcept RuntimeError as e:\n    if 'hash mismatch' in str(e):\n        # Package may be corrupted on the mirror\n        print(f'Hash mismatch for {package.path}. Consider updating the lockfile.')\n        print('Run: android-sdk-manager.py add-to-lockfile <lockfile> <package>')\n    raise","preventionTips":["Keep the lockfile updated — re-run add-to-lockfile when Google updates packages.","Verify mirror integrity periodically by spot-checking package hashes.","Use HTTPS and verify no proxy modifies downloaded content."],"tags":["ci","android","sdk","checksum","integrity","python"],"backgroundTag":null,"analyzedSha":"7088e4b63a9516ebfbfe2ab2d999cf01a528ac14","analyzedAt":"2026-08-10T14:17:03.603Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}