pypa/pip · error · ResolutionTooDeepError

resolution-too-deep

resolution-too-deep

Error message

Dependency resolution exceeded maximum depth

What it means

Raised as ResolutionTooDeepError (pip's own exception, code 'resolution-too-deep') at line 113-114 when the underlying resolvelib RLResolver.resolve() raises ResolutionTooDeep — i.e., the resolver exceeded max_rounds=200000 (line 102-104) without reaching a fixed point. The dependency graph is too complex/exponentially branching for the backtracking resolver to complete within the round budget.

Source

Thrown at src/pip/_internal/resolution/resolvelib/resolver.py:114

        resolver: RLResolver[Requirement, Candidate, str] = RLResolver(
            provider,
            reporter,
        )

        try:
            limit_how_complex_resolution_can_be = 200000
            result = self._result = resolver.resolve(
                collected.requirements, max_rounds=limit_how_complex_resolution_can_be
            )

        except ResolutionImpossible as e:
            error = self.factory.get_installation_error(
                cast("ResolutionImpossible[Requirement, Candidate]", e),
                collected.constraints,
            )
            raise error from e
        except ResolutionTooDeep:
            raise ResolutionTooDeepError from None

        req_set = RequirementSet(check_supported_wheels=check_supported_wheels)
        # process candidates with extras last to ensure their base equivalent is
        # already in the req_set if appropriate.
        # Python's sort is stable so using a binary key function keeps relative order
        # within both subsets.
        for candidate in sorted(
            result.mapping.values(), key=lambda c: c.name != c.project_name
        ):
            ireq = candidate.get_install_requirement()
            if ireq is None:
                if candidate.name != candidate.project_name:
                    # extend existing req's extras
                    with contextlib.suppress(KeyError):
                        req = req_set.get_requirement(candidate.project_name)
                        req_set.add_named_requirement(
                            install_req_extend_extras(
                                req, get_requirement(candidate.name).extras

View on GitHub (pinned to f399c37189)

Solutions

  1. Pin the most contested packages to exact versions (==) to drastically prune the backtracking search space.
  2. Upgrade pip to the latest version, which contains resolver performance improvements that reduce rounds.
  3. Reduce simultaneous requirements: install in stages, or trim unused extras from pip install lines.
  4. Add constraints (-c constraints.txt) to cap version ranges for transitive dependencies.

Example fix

// before
pip install pkg-a pkg-b pkg-c pkg-d  # all loosely pinned / unpinned

// after
pip install 'pkg-a==2.1.0' 'pkg-b==1.4.2' pkg-c pkg-d
Defensive patterns

Strategy: fallback

Validate before calling

def estimate_resolution_risk(req_lines):
    # heuristic: unpinned (no ==) requirements increase backtracking
    unpinned = [r for r in req_lines if '==' not in r and '@' not in r]
    return len(unpinned), len(unpinned) > 5

Try / catch

import subprocess, sys
try:
    subprocess.run([sys.executable, '-m', 'pip', 'install', *reqs], check=True)
except subprocess.CalledProcessError as e:
    if 'resolution-too-deep' in (e.stdout or '') + (e.stderr or ''):
        # retry with exact pins / constraints
        subprocess.run([sys.executable, '-m', 'pip', 'install', *pinned_reqs], check=True)
    raise

Prevention

When it happens

Trigger: Running pip install on a set of requirements whose dependency graph is pathologically large or contains many overlapping version constraints causing massive backtracking; installing many packages with conflicting or very loose version specifiers simultaneously; environments where prereleases, many extras, and platform markers multiply candidate combinations past 200000 rounds.

Common situations: A requirements.txt with unpinned or loosely-pinned (>=) dependencies across many transitive packages; circular-ish or diamond dependency chains with many valid version combinations; an index serving huge numbers of versions for involved packages; an old pip version with a less optimized resolver.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/e639525e126e925d. Report an issue: GitHub.