{"record":{"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":"critical","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/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/utils/hashes.py#L75-L111","documentation":"Raised as HashMismatch by Hashes._raise (hashes.py:93) when none of the computed digests of a downloaded archive match any of the expected digests listed in the requirements file. This is pip's tamper-detection mechanism for --require-hashes mode: if even one file's hash differs from what was pinned, pip aborts to prevent installing potentially compromised or altered packages. The exception carries both the expected (allowed) and computed (gotten) hashes for diagnostics.","triggerScenarios":"check_against_chunks / check_against_file is called after downloading an archive, iterates all expected hash algorithms, computes the actual digest, and if none match any entry in self._allowed[hash_name] for any algorithm, calls _raise at line 90. This happens during install with --require-hashes or when any requirement has a hash.","commonSituations":"Updating a package version in requirements.txt without regenerating its hash. A requirements file whose hashes were generated for a different file (different platform wheel vs sdist). Man-in-the-middle attack or compromised mirror serving a tampered package. Transitive dependency pinning changes that shift which file is downloaded.","solutions":["If you intentionally changed package versions, regenerate all hashes: delete the hashes, run `pip install --require-hashes -r requirements.txt`, and pip will print the correct hashes in the HashMissing error to add.","Use `pip hash <downloaded-file>` to compute the correct sha256 for the exact file being installed.","Ensure your index URL / mirror is serving the correct, unmodified files.","Verify you are not mixing platform-specific wheels with hashes computed from a different platform's wheel."],"exampleFix":"// before\npkg==1.0 --hash=sha256:aaaa...\n  (actual download hashes to bbbb...)\n\n// after\npkg==1.0 --hash=sha256:bbbb...\n  (run: pip hash pkg-1.0-py3-none-any.whl to get bbbb)","handlingStrategy":"try-catch","validationCode":"import hashlib\n\ndef verify_archive_hash(filepath: str, expected_sha256: str) -> bool:\n    \"\"\"Pre-verify a downloaded file's sha256 before handing to pip.\"\"\"\n    h = hashlib.sha256()\n    with open(filepath, 'rb') as f:\n        for chunk in iter(lambda: f.read(8192), b''):\n            h.update(chunk)\n    return h.hexdigest() == expected_sha256.lower()","typeGuard":null,"tryCatchPattern":"from pip._internal.exceptions import HashMismatch\n\ntry:\n    # pip install / download operation\n    pass\nexcept HashMismatch as e:\n    # e has .allowed and .gotten attributes for diagnostics\n    print(f'Hash mismatch: expected {e.allowed}, got {e.gotten}')\n    # Re-download, regenerate lock file, or alert on potential tampering","preventionTips":["Regenerate all hashes whenever you change package versions in a lock file.","Use pip-tools (`pip-compile --generate-hashes`) to keep hashes in sync automatically.","Pin exact versions and verify your index/mirror serves correct files.","Treat a hash mismatch on an unmodified lock as a potential security incident."],"tags":["hashes","security","tamper-detection","require-hashes","integrity"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}