{"id":"a1fefd2fb0d9c22d","repo":"pypa/pip","slug":"could-not-install-locked-package-project-name-r","errorCode":null,"errorMessage":"Could not install locked package {project_name!r} from {locked_link.comes_from!r}: {detail}","messagePattern":"Could not install locked package (.+?) from (.+?): (.+?)","errorType":"exception","errorClass":"InstallationError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/index/package_finder.py","lineNumber":902,"sourceCode":"        All versions found are returned as an InstallationCandidate list.\n\n        See LinkEvaluator.evaluate_link() for details on which files\n        are accepted.\n        \"\"\"\n        if project_name in self._all_candidates:\n            return self._all_candidates[project_name]\n\n        link_evaluator = self.make_link_evaluator(project_name)\n\n        if locked_link := self._locked_links.get(canonicalize_name(project_name)):\n            # If a locked link is known for that project, do not check\n            # index_urls nor find_links. We don't use get_install_candidate here,\n            # because if a locked link is unsupported (due to format control,\n            # release control or otherwise), we want to error out immediately\n            # instead of ignoring it.\n            result, detail = link_evaluator.evaluate_link(locked_link)\n            if result != LinkType.candidate:\n                raise InstallationError(\n                    f\"Could not install locked package {project_name!r} \"\n                    f\"from {locked_link.comes_from!r}: {detail}\"\n                )\n            self._all_candidates[project_name] = [\n                InstallationCandidate(project_name, detail, locked_link, locked=True)\n            ]\n            return self._all_candidates[project_name]\n\n        collected_sources = self._link_collector.collect_sources(\n            project_name=project_name,\n            candidates_from_page=functools.partial(\n                self.process_project_url,\n                link_evaluator=link_evaluator,\n            ),\n        )\n\n        page_candidates_it = itertools.chain.from_iterable(\n            source.page_candidates()","sourceCodeStart":884,"sourceCodeEnd":920,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/index/package_finder.py#L884-L920","documentation":"InstallationError raised in find_best_candidate when a package is being installed from a locked link (a pre-pinned file from a lockfile) but that link fails the link evaluator's acceptance checks (format control, release control, requires-python, yank, etc.). Because locked links are explicit user intent, pip errors rather than silently ignoring them.","triggerScenarios":"Reached when self._locked_links contains a Link for the canonical project name (set via add_locked_link, typically from a constraints/lockfile) and link_evaluator.evaluate_link(locked_link) returns anything other than LinkType.candidate - e.g. the locked wheel is for the wrong Python version, is yanked, or excluded by --only-binary.","commonSituations":"A lockfile pins a wheel that is incompatible with the current interpreter (requires-python mismatch); the locked file was yanked upstream; format-control flags (--no-binary/--only-binary) exclude the locked artifact; the locked URL is no longer reachable/acceptable.","solutions":["Read {detail} to see why the evaluator rejected the locked link and address that specific reason first.","Regenerate the lockfile on the target platform so the pinned artifact is actually compatible.","Loosen format/release control flags that exclude the locked artifact (--no-binary / --only-binary / prerelease policy).","If the locked version was yanked, update the lock to a non-yanked release."],"exampleFix":"# before - lock pins cp39 wheel, you run cp311\n# lockfile: somepkg==1.0 --hash=... (cp39 wheel)\npip install -r locked-requirements.txt\n\n# after - regenerate lock for the current interpreter\npip-compile --python-version 3.11 requirements.in","handlingStrategy":"validation","validationCode":"# validate a locked link will pass the evaluator before installing\nfrom pip._internal.index.collector import LinkCollector\nfrom pip._internal.models.target_python import TargetPython\n# pseudo: evaluate_link(locked_link) must == LinkType.candidate\nresult, detail = link_evaluator.evaluate_link(locked_link)\nif result.name != 'candidate':\n    print('locked link will be rejected:', detail)","typeGuard":"def locked_link_accepted(link_evaluator, link) -> bool:\n    from pip._internal.index.package_finder import LinkType\n    result, _ = link_evaluator.evaluate_link(link)\n    return result == LinkType.candidate","tryCatchPattern":"from pip._internal.exceptions import InstallationError\ntry:\n    finder.find_best_candidate(project, req)\nexcept InstallationError as e:\n    if 'Could not install locked package' in str(e):\n        # regenerate lock for this platform\n        ...","preventionTips":["Generate lockfiles per-target-platform so locked artifacts are compatible.","Avoid --only-binary/--no-binary settings that exclude locked artifacts.","Do not lock yanked files.","Re-run the lock whenever the target interpreter changes."],"tags":["lockfile","constraints","link-evaluator","resolution"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}