pypa/pip · error · InstallationError

Could not satisfy constraints for '{install_req.name}': inst

Error message

Could not satisfy constraints for '{install_req.name}': installation from path or url cannot be constrained to a version

What it means

Raised by the legacy resolver when a package is both requested for installation from a path/URL and constrained by a -c constraints file, but the constraint's link path differs from the install link path. The legacy resolver cannot pin a path/URL source to a version, so it refuses rather than guess. This path is only hit when the new resolver is disabled (--use-deprecated=legacy-resolver) or unavailable.

Source

Thrown at src/pip/_internal/resolution/legacy/resolver.py:285

            )

        # When no existing requirement exists, add the requirement as a
        # dependency and it will be scanned again after.
        if not existing_req:
            requirement_set.add_named_requirement(install_req)
            # We'd want to rescan this requirement later
            return [install_req], install_req

        # Assume there's no need to scan, and that we've already
        # encountered this for scanning.
        if install_req.constraint or not existing_req.constraint:
            return [], existing_req

        does_not_satisfy_constraint = install_req.link and not (
            existing_req.link and install_req.link.path == existing_req.link.path
        )
        if does_not_satisfy_constraint:
            raise InstallationError(
                f"Could not satisfy constraints for '{install_req.name}': "
                "installation from path or url cannot be "
                "constrained to a version"
            )
        # If we're now installing a constraint, mark the existing
        # object for real installation.
        existing_req.constraint = False
        # If we're now installing a user supplied requirement,
        # mark the existing object as such.
        if install_req.user_supplied:
            existing_req.user_supplied = True
        existing_req.extras = tuple(
            sorted(set(existing_req.extras) | set(install_req.extras))
        )
        logger.debug(
            "Setting %s extras to: %s",
            existing_req,
            existing_req.extras,

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Switch to the default (new) resolver by removing --use-deprecated=legacy-resolver; it handles path/URL + constraints differently.
  2. Remove the conflicting version constraint for this package from your -c constraints file, or make the constraint point at the same path/URL.
  3. If you must constrain, constrain by the exact same path/URL in both the requirements and the constraints file so link.path matches.
  4. Install the path/URL package without the constraint flag, then add it back once the version is known.

Example fix

# before (legacy resolver + conflicting constraint)
pip install --use-deprecated=legacy-resolver -c constraints.txt ./myfork
cat constraints.txt  # mypkg==1.2

# after: drop the version pin for the path-installed package
# constraints.txt: (remove mypkg line)
pip install -c constraints.txt ./myfork
Defensive patterns

Strategy: validation

Validate before calling

def validate_constraint_compatibility(install_reqs, constraints):
    # legacy-resolver only: every path/url install must not have a conflicting constraint link
    cons_by_name = {c.name: c for c in constraints}
    for ireq in install_reqs:
        c = cons_by_name.get(ireq.name)
        if ireq.link and c is not None and c.link is not None:
            if ireq.link.path != c.link.path:
                raise SystemExit(
                    f"Constraint for {ireq.name} points at a different path than the "
                    f"install requirement; the legacy resolver cannot satisfy this."
                )
# run before invoking pip with -c

Prevention

When it happens

Trigger: In _resolve_one: install_req has a link, existing_req is a constraint, and (existing_req.link is None OR install_req.link.path != existing_req.link.path). Concretely: requirements file has `./myfork` (or a git+ URL) while constraints file pins `mypkg==1.2` or points to a different path, run under the legacy resolver.

Common situations: Mixing editable/path/VCS installs with version constraints in a constraints file; migrating a constraints file that pins versions for packages you now install from a local checkout; CI that pins `-c constraints.txt` while also installing a fork from a URL.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/39dd1d953f0ff866.json. Report an issue: GitHub.