{"id":"c891aa1a416ec578","repo":"pypa/pip","slug":"can-t-verify-hashes-for-these-requirements-because","errorCode":null,"errorMessage":"Can't verify hashes for these requirements because we don't have a way to hash version control repositories:","messagePattern":"Can't verify hashes for these requirements because we don't have a way to hash version control repositories:","errorType":"exception","errorClass":"VcsHashUnsupported","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/operations/prepare.py","lineNumber":474,"sourceCode":"            parallel_builds=parallel_builds,\n        )\n        req.ensure_pristine_source_checkout()\n\n    def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes:\n        # By the time this is called, the requirement's link should have\n        # been checked so we can tell what kind of requirements req is\n        # and raise some more informative errors than otherwise.\n        # (For example, we can raise VcsHashUnsupported for a VCS URL\n        # rather than HashMissing.)\n        if not self.require_hashes:\n            return req.hashes(trust_internet=True)\n\n        # We could check these first 2 conditions inside unpack_url\n        # and save repetition of conditions, but then we would\n        # report less-useful error messages for unhashable\n        # requirements, complaining that there's no hash provided.\n        if req.link.is_vcs:\n            raise VcsHashUnsupported()\n        if req.link.is_existing_dir():\n            raise DirectoryUrlHashUnsupported()\n\n        # Unpinned packages are asking for trouble when a new version\n        # is uploaded.  This isn't a security check, but it saves users\n        # a surprising hash mismatch in the future.\n        # file:/// URLs aren't pinnable, so don't complain about them\n        # not being pinned.\n        if not req.is_direct and not req.is_pinned:\n            raise HashUnpinned()\n\n        # If known-good hashes are missing for this requirement,\n        # shim it with a facade object that will provoke hash\n        # computation and then raise a HashMissing exception\n        # showing the user what the hash should be.\n        return req.hashes(trust_internet=False) or MissingHashes()\n\n    def _fetch_metadata_only(","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/operations/prepare.py#L456-L492","documentation":"Raised as VcsHashUnsupported when --require-hashes is active and a requirement is backed by a version-control URL (git+, hg+, svn+, bzr+). At prepare.py:473-474, _get_linked_req_hashes checks req.link.is_vcs and aborts because there is no single, stable file to hash for a VCS checkout.","triggerScenarios":"Running pip install --require-hashes with a requirements file that contains a VCS requirement such as 'git+https://github.com/org/repo.git@abc123#egg=pkg'. Hash verification has no reproducible artifact to checksum, so pip refuses.","commonSituations":"Pinning a repo in a hashed lockfile. Mixing development VCS checkouts into a hashed, reproducible build. CI enforcing --require-hashes but a dependency pulls a git URL.","solutions":["Replace the VCS requirement with a pinned sdist/wheel URL that includes a sha256 hash.","Build a wheel from the VCS checkout once and reference that wheel (with its hash) in the requirements file.","Drop --require-hashes for that environment if VCS requirements are truly required (reduces reproducibility guarantees).","Vendor the dependency into the repo and install it as a local directory after pinning a known revision."],"exampleFix":"# before (requirements.txt with --require-hashes)\ngit+https://github.com/org/repo.git@abc123#egg=pkg\n\n# after: build wheel, pin by hash\npkg @ https://my-mirror/pkg-1.0-py3-none-any.whl \\\n  --hash=sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","handlingStrategy":"validation","validationCode":"def validate_no_vcs_under_require_hashes(requirements_file):\n    with open(requirements_file) as f:\n        for line in f:\n            line = line.strip()\n            if line and not line.startswith(\"#\") and \"+\" in line.split(\":\")[0]:\n                scheme = line.split(\"+\", 1)[0]\n                if scheme in (\"git\", \"hg\", \"svn\", \"bzr\"):\n                    raise SystemExit(f\"VCS requirement cannot be hashed: {line}\")","typeGuard":"def is_vcs_url(url: str) -> bool:\n    return any(url.startswith(p) for p in (\"git+\", \"hg+\", \"svn+\", \"bzr+\"))","tryCatchPattern":null,"preventionTips":["Avoid VCS requirements when --require-hashes is on.","Pre-build wheels from VCS checkouts and pin them by hash.","Document which deps are incompatible with hash mode in your lockfile."],"tags":["hashes","require-hashes","vcs","security","install"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}