pip "--find-links" Finds No Candidate for a Local Wheel in CI
pip can install from a local wheel directory via --find-links, but it only considers files whose name and platform tag match the requirement and the runner. A wrong path, an arch/Python tag mismatch, or a name mismatch leaves pip with no candidate.
What this error means
An offline/local install with --find-links ./wheels fails with "No matching distribution found" even though a wheel for the package sits in that directory. The file exists, but its tag or name does not match what pip is resolving for.
ERROR: Could not find a version that satisfies the requirement mypkg==1.2.0
(from versions: none)
ERROR: No matching distribution found for mypkg==1.2.0
# despite ./wheels/mypkg-1.2.0-cp311-cp311-manylinux_2_17_x86_64.whl present
# (runner is cp312 / arm64)Common causes
Wheel tag does not match the runner
The local wheel is tagged for a different Python (cp311 vs cp312), libc, or arch, so pip filters it out and reports no candidate.
Wrong directory or name mismatch
The --find-links path is wrong, or the requirement name does not match the wheel’s distribution name, so pip never considers the file.
How to fix it
Build/fetch a wheel that matches the runner
Provide a wheel whose Python/arch tag matches the interpreter doing the install.
python -c "import sys,platform; print(sys.version_info, platform.machine())"
# place a matching cp312 / correct-arch wheel in ./wheels, then:
pip install --no-index --find-links ./wheels mypkg==1.2.0Confirm the path and offline flags
- Verify
./wheelsactually contains the wheel (ls ./wheels). - Use
--no-indexwith--find-linksfor a fully offline install so pip does not silently fall back to PyPI. - Match the requirement name to the wheel’s distribution name exactly.
How to prevent it
- Build local wheels for the exact interpreter/arch the runner uses.
- Pair
--find-linkswith--no-indexfor reproducible offline installs. - Name and tag local wheels to match the resolving requirement.