How do you read pip's ResolutionImpossible report to find which requirements actually conflict?
answer
- The error explains itself if read closely
- One line per requester
- Yours versus somebody else's requirement
- Intersect the demanded ranges
- The last combination tried, not always the cause
basics
~20 sRead the block headed "The conflict is caused by": each line names a requester and the range it demands. Lines saying the user requested something are your own direct requirements; the rest are transitive. Those ranges share no version.
solid answer
~50 spip's conflict report has two useful parts. The header names what it could not install, and then a block lists one line per requester with the exact range each one demands — lines beginning with the user requested are requirements you supplied directly, and lines of the form `pkg-a 3.1 depends on shared-lib>=2.0` are transitive, with the requester's own version shown. You are looking for a pair whose ranges have no version in common. pip then offers generic advice about loosening your specified ranges or removing versions so it can search further. Two cautions: because the resolver backtracks, the report describes the last combination it tried, which is sometimes a symptom rather than the root cause; and a message about no matching distribution is a different failure entirely — no candidate exists for your interpreter or platform, not a conflict between requirements.
go deeper
Recall that the error text names the conflicting requirements explicitly and is meant to be read, not retried. Being able to point at the two lines that demand incompatible ranges is already a good answer at this level.
Explain the structure line by line: requester, requester version, demanded range, and the difference between a requirement you supplied and one that arrived transitively. Then show that the conflict is an empty intersection of ranges.
Show that you reduce the problem rather than trusting the printout: minimal reproduction in a scratch environment, verbose output to see the search, walking the requirement chain, and distinguishing a genuine conflict from a missing candidate for your interpreter or platform.
Own what happens after the diagnosis. Set the expectation that a conflict is a decision about which constraint the organization gives up, that bypassing dependency checks to ship is a deferred outage, and that repeated conflicts are a signal about dependency-count and upper-bound policy.
## What the report is telling you When pip's resolver proves that no set of versions satisfies everything, it fails with a conflict report — the failure pip's internals call *resolution impossible*. A representative one: ```text ERROR: Cannot install pkg-a and pkg-b==2.0 because these package versions have conflicting dependencies. The conflict is caused by: The user requested shared-lib==1.4 pkg-a 3.1 depends on shared-lib>=2.0 pkg-b 2.0 depends on shared-lib<1.5 To fix this you could try to: 1. loosen the range of package versions you've specified 2. remove package versions to allow pip to attempt to solve the dependency conflict ``` Read it in three passes. **Pass one: who is asking.** Every line in the conflict block is a *requester*. `The user requested ...` means the requirement came from you — a command-line argument or your requirements input. Every other line has the form `<requester> <its version> depends on <range>`, and the requester's own version matters: `pkg-a 3.1` is the specific release whose metadata carries that range, which tells you immediately whether a different `pkg-a` release might carry a different one. **Pass two: intersect the ranges.** Collect the ranges demanded of the same distribution and ask whether any version satisfies all of them. In the example, `>=2.0` and `<1.5` are disjoint, and the user's `==1.4` satisfies one of them and not the other. That is the whole conflict. If the intersection is non-empty but no release exists inside it, you have a different problem — a gap in the release history rather than contradictory constraints. **Pass three: decide whose constraint is soft.** Your own pin is usually the softest, which is why pip's first suggestion is to loosen what you specified. An upper cap in a third party's metadata is harder, but not immovable — caps are frequently defensive and stale, and a newer release of that requester often widens them. ## Finding the requester the report does not name Often the distribution at the centre of the conflict is one you have never heard of, because it is transitive. For anything already installed, `python -m pip show <name>` prints both what it requires and what requires it, which walks the chain in the direction you need. For metadata you want to inspect programmatically, `importlib.metadata` reads the same installed `.dist-info` records from the standard library. For candidates that are not installed, the report itself is the metadata: it already printed the requester version and its range. ## When the report names the wrong culprit This is the subtlety worth carrying into an interview. The resolver backtracks, so by the time it gives up it may have wandered far from your actual requirements, and the combination it prints is the last one it tried, not necessarily the minimal explanation. Two habits fix it: * **Reduce the problem.** Try to install the two suspected requesters alone in a scratch environment. If they conflict on their own, you have the minimal reproduction; if they do not, something else in your requirement set is forcing the situation. * **Turn up verbosity.** Verbose output shows the search as it happens, which reveals which requirement kept pushing the resolver backwards before it failed. ## The failure that looks similar but is not a conflict `No matching distribution found for shared-lib==1.4` is not a conflict report. It means no candidate is installable at all: the version does not exist on the configured index, or every candidate is excluded by its declared `Requires-Python` range or by platform compatibility — for example, on a recently released interpreter for which no compatible wheel has been published. The diagnosis is completely different: you check what the index offers and what your interpreter is, rather than hunting for a contradictory pair. ## After you have read it The report tells you what is unsatisfiable; it does not tell you which constraint to give up. That decision — loosen your own pin, upgrade the capping requester, drop a dependency, or separate the two consumers — is the judgement call, and it belongs to whoever understands what the two consumers are for. Reading the report accurately is what stops that decision from being made by guesswork.
- The report names a distribution you never asked for. How do you find who pulled it in?It is transitive, and the report has already half-answered it: each line names the requester and the requester's version. For anything installed, `python -m pip show <name>` lists both what it requires and what requires it, so you can walk upwards to your own direct dependency. From the standard library, `importlib.metadata` reads the same installed metadata if you want to script the traversal.
- When is the conflict the report prints not the real root cause?When the resolver backtracked a long way before failing, the printed combination is the last one it tried rather than the minimal explanation. Reproduce it small — install the two suspected requesters alone in a scratch environment — and use verbose output to see which requirement kept forcing the search backwards. If the pair does not conflict in isolation, something else in your set is driving it.
- How is a no-matching-distribution error different from a conflict report?It is not a contradiction between requirements at all. It means no installable candidate exists: the version is absent from the configured index, or every candidate is ruled out by its declared `Requires-Python` range or by platform compatibility. You diagnose it by checking what the index actually offers for your interpreter and platform, not by hunting for two incompatible requesters.
saying these in an interview costs you the question
- Retries the same install command hoping for a different result
- Clears the cache and reinstalls instead of reading the report
- Cannot tell a direct requirement from a transitive one in the output
- Assumes the printed pair is always the minimal cause
- Treats no-matching-distribution as a version conflict
- Immediately bypasses dependency checking to force the install through