{"id":"563e730230e25926","repo":"pypa/pip","slug":"these-packages-do-not-match-the-hashes-from-the-re","errorCode":null,"errorMessage":"THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.","messagePattern":"THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE\\. If you have updated the package versions, please update the hashes\\. Otherwise, examine the package contents carefully; someone may have tampered with them\\.","errorType":"exception","errorClass":"HashMismatch","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/utils/hashes.py","lineNumber":93,"sourceCode":"        \"\"\"\n        gots = {}\n        for hash_name in self._allowed.keys():\n            try:\n                gots[hash_name] = hashlib.new(hash_name)\n            except (ValueError, TypeError):\n                raise InstallationError(f\"Unknown hash name: {hash_name}\")\n\n        for chunk in chunks:\n            for hash in gots.values():\n                hash.update(chunk)\n\n        for hash_name, got in gots.items():\n            if got.hexdigest() in self._allowed[hash_name]:\n                return\n        self._raise(gots)\n\n    def _raise(self, gots: dict[str, _Hash]) -> NoReturn:\n        raise HashMismatch(self._allowed, gots)\n\n    def check_against_file(self, file: BinaryIO) -> None:\n        \"\"\"Check good hashes against a file-like object\n\n        Raise HashMismatch if none match.\n\n        \"\"\"\n        return self.check_against_chunks(read_chunks(file))\n\n    def check_against_path(self, path: str) -> None:\n        with open(path, \"rb\") as file:\n            return self.check_against_file(file)\n\n    def has_one_of(self, hashes: Mapping[str, str]) -> bool:\n        \"\"\"Return whether any of the given hashes are allowed.\"\"\"\n        for hash_name, hex_digest in hashes.items():\n            if self.is_hash_allowed(hash_name, hex_digest):\n                return True","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/utils/hashes.py#L75-L111","documentation":"HashMismatch (the headline 'THESE PACKAGES DO NOT MATCH THE HASHES...') raised by _raise() when none of the computed digests of the downloaded archive match any allowed digest in the requirements file. It signals either a legitimate version drift (hashes not refreshed after a version bump) or, worst case, a tampered/MITM'd artifact.","triggerScenarios":"check_against_chunks computes gots for each allowed algorithm and none of got.hexdigest() values appear in self._allowed[hash_name]. Happens after download when --require-hashes is on or any requirement carries --hash and the archive bytes don't match.","commonSituations":"Bumped a version in requirements.txt but forgot to re-run pip-compile/hash; a mirror serving a cached-but-different file; a corporate proxy re-packaging wheels; an actual supply-chain attack; cross-posting a file that was re-uploaded in place.","solutions":["If you intentionally changed versions, regenerate hashes with `pip hash <file>` or pip-compile and update the requirements file.","Verify the downloaded archive against the publisher's official checksum before trusting new hashes.","Clear pip's cache (pip cache purge) and the mirror cache to rule out a stale/corrupt cached file.","If you did not change anything, treat as a possible tamper: do NOT just update the hash — investigate the source."],"exampleFix":"# before\npkg==1.0 --hash=sha256:OLDHASH...\n# (you bumped to 1.1 but left the 1.0 hash)\n\n# after - regenerate for the actual archive\npip download pkg==1.1 --no-deps -d /tmp/p\npip hash /tmp/p/pkg-1.1*.whl   # paste output back into requirements.txt","handlingStrategy":"validation","validationCode":"import hashlib\n\ndef verify_archive_hash(path, expected_alg, expected_hex):\n    h = hashlib.new(expected_alg)\n    with open(path, 'rb') as f:\n        for chunk in iter(lambda: f.read(1 << 16), b''):\n            h.update(chunk)\n    if h.hexdigest() != expected_hex:\n        raise ValueError(f\"{expected_alg} mismatch for {path}\")\n# run before pip if you pre-download archives; never auto-update on mismatch without trust review","typeGuard":null,"tryCatchPattern":"try:\n    pip_install('-r', 'reqs.txt')\nexcept HashMismatch as e:\n    # only safe to auto-refresh if you intentionally changed versions\n    if versions_intentionally_bumped('reqs.txt'):\n        regenerate_hashes('reqs.txt')\n        pip_install('-r', 'reqs.txt')\n    else:\n        raise  # possible tamper — do NOT paper over it","preventionTips":["Regenerate hashes with pip-compile/pip hash whenever you change a version.","Verify downloaded files against upstream-published checksums.","Purge pip cache and mirror caches if mismatches appear unexpectedly."],"tags":["pip","hashes","require-hashes","security","supply-chain","verification"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}