Fix: Poetry Dependency Conflict (SolverProblemError / No Solution Found)
Part of: Python Errors
Quick Answer
How to fix Poetry dependency resolution errors — SolverProblemError when adding packages, conflicting version constraints, how to diagnose dependency trees, and workarounds for incompatible packages.
The Error
Running poetry add some-package or poetry install fails with:
SolverProblemError
Because myproject depends on package-a (^2.0) and package-b (^3.0)
and package-b (3.0.0) depends on package-a (^1.0),
package-a cannot be both >=2.0,<3.0 and >=1.0,<2.0.
So, because myproject depends on package-a (^2.0), version solving failed.Or when adding a new package:
Because requests (2.31.0) depends on urllib3 (<3,>=1.21.1)
and your project depends on urllib3 (^2.0), requests is forbidden.Or after pulling a project:
poetry install
...
PackageNotFound: Package pandas (1.5.0) not found.Why This Happens
Poetry’s resolver is built on Mixology, a port of the Dart language’s pub solver — a backtracking SAT-style algorithm that explores the dependency graph and proves either a satisfying assignment or a conflict explanation. When you see SolverProblemError, the solver has explored the available versions and arrived at a contradiction. The explanation it prints is not just an error message; it is the literal chain of derivations the solver used to prove the conflict. That is why the explanation is sometimes long: it traces upstream packages that you do not directly depend on.
The conflict is usually one of three shapes. Direct constraint contradiction is the obvious case — requests >=2.32 and requests <2.30 in the same project cannot coexist. Transitive contradiction is more common: you do not declare the conflicting package, but two of your dependencies pull in incompatible versions of a shared sub-dependency (often urllib3, pydantic, httpcore, or protobuf). Marker contradiction is the subtle case: a constraint is conditioned on python_version or sys_platform and Poetry must find a version that works across every platform you target.
There is also a class of problems that look like solver issues but are not. A PackageNotFound after poetry install usually means a package version recorded in poetry.lock has been yanked from PyPI — the resolver succeeded once but the world has changed. The Resolving dependencies... step hanging for tens of minutes is usually Poetry probing every version on PyPI for a transitive dependency that has hundreds of releases (the classic example is boto3). Both look like conflicts and neither is really one.
- Direct conflict — package A requires
requests>=2.28and package B requiresrequests<2.28. Both cannot be true. - Transitive conflict — you don’t directly depend on the conflicting package, but two of your dependencies pull in incompatible versions of a shared sub-dependency.
- Overly strict constraints — your
pyproject.tomlpins a version too tightly (e.g.,urllib3 = "1.26.0"instead ofurllib3 = ">=1.26.0"). - Python version incompatibility — a package you are trying to install only supports Python 3.10+, but your project targets Python 3.9.
- Lock file out of sync — the
poetry.lockreferences a package version that no longer exists on PyPI (yanked release).
Version History That Changes the Failure Mode
The Poetry CLI has shipped several behavior changes that affect how conflicts are reported and resolved. Identify your version with poetry --version before applying any fix from older threads:
- Poetry 1.2 (August 2022) — Introduced the plugin system, dependency groups (
[tool.poetry.group.dev.dependencies]replacing[tool.poetry.dev-dependencies]), and thepoetry-corebuild backend split. The solver was rewritten to handle markers more aggressively, which surfaced previously-silent transitive conflicts as newSolverProblemErrors after the upgrade. - Poetry 1.3 (December 2022) — Stabilized the new lock format. Removed legacy
setup.py-based installs in favor of PEP 517 builds.poetry exportwas moved into a separate plugin. - Poetry 1.4 (February 2023) — Lockfile format v2 became the default. The old v1 format is still readable but new locks are written in v2. Mixed-version teams (one developer on 1.3, another on 1.4) end up rewriting the lock file on every commit, which looks like a phantom conflict.
- Poetry 1.5 (May 2023) — Added explicit source priorities:
default,primary,supplemental,explicit. Replaced the deprecatedsecondarysource mode. If you depend on a private PyPI mirror, you now have to set its priority correctly or Poetry will fall back to public PyPI and produce different solutions. - Poetry 1.6 (August 2023) — Added
poetry lock --no-updatesemantics for lockfile-only mode and removedsetup.py egg_infoshim. Improved error messages for marker conflicts. - Poetry 1.7 (November 2023) — Added
poetry self addfor plugins and reworked the keyring backend selection. Compatibility withpip 23.x’s new resolver was reported as smoother (fewer false-positive solves that fail at install time). - Poetry 1.8 (February 2024) — Added the install-completer for fast partial installs, and made
poetry lockre-check published packages by default. Means a yanked release is now caught at lock time, not at install time. - Poetry 2.0 (December 2024) — Adopted PEP 621 for project metadata.
[project]is preferred over[tool.poetry]for the basic fields (name,version,dependencies), though the tool-specific configuration stays under[tool.poetry]. Migration is one-way; once you adopt 2.0 format, older Poetry versions cannot read it.
If you upgraded from 1.4 to 1.5+ and started seeing private-index packages drop out of the lock file, the cause is the new source priority semantics. Re-declare the index with priority = "primary" (or explicit if it should only be used for named packages). The pip 23+ resolver also rejects some packages that older Poetry locks accepted; if pip install -r requirements.txt exported from Poetry fails, regenerate the export with poetry export -f requirements.txt --without-hashes.
Fix 1: Diagnose the Conflict
Before fixing, understand exactly what is conflicting:
# Show the full dependency tree
poetry show --tree
# Show why a specific package is installed and what requires it
poetry show requests
# Output shows: required by, version installed, dependencies
# Check what version constraints are on a package
poetry show --tree | grep -A5 "urllib3"
# See all packages and their versions
poetry show
# Check for outdated packages
poetry show --outdatedRead the error message carefully. Poetry’s error messages are detailed — they tell you exactly which packages conflict and why:
Because httpx (0.24.0) depends on httpcore (>=0.17.0,<0.18.0)
and aiohttp (3.8.5) depends on httpcore (>=0.16.0,<0.17.0),
httpx and aiohttp are incompatible.This tells you httpx and aiohttp cannot coexist in their current versions because they require different httpcore ranges.
Fix 2: Relax Version Constraints
Overly strict pinning in pyproject.toml is the most common fixable cause:
# pyproject.toml — before (too strict)
[tool.poetry.dependencies]
python = "^3.9"
requests = "2.28.0" # Exact pin — inflexible
urllib3 = "^1.26" # May conflict with requests' requirements
# After — relaxed constraints
[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28" # Allow any 2.28.x or higher (within major)
urllib3 = ">=1.26,<3" # Allow 1.x or 2.xCommon constraint syntax:
package = "^2.0" # >=2.0.0, <3.0.0 (caret — most common)
package = "~2.1" # >=2.1.0, <2.2.0 (tilde — patch-level)
package = ">=2.0" # Any version 2.0 or higher
package = ">=2.0,<3" # Range
package = "*" # Any versionAfter relaxing constraints:
poetry update package-name # Re-resolve with new constraintsFix 3: Update the Conflicting Package
Often the conflict is because you are requesting a new package that requires a newer version of a shared dependency than your existing packages allow:
# Update a specific package that is causing the conflict
poetry update urllib3
# Update all packages to their latest compatible versions
poetry update
# Add a package and allow Poetry to upgrade dependencies
poetry add new-package --no-interactionCheck if a newer version of the conflicting package resolves it:
# See available versions of a package
poetry search some-package
# Or check PyPI directly
pip index versions some-packageFix 4: Use Dependency Groups to Isolate Conflicts
If the conflict is between development and production dependencies, separate them into groups:
# pyproject.toml
[tool.poetry.dependencies]
python = "^3.11"
fastapi = "^0.104"
sqlalchemy = "^2.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4"
black = "^23.0"
# Dev tools with conflicting deps go here — isolated from production
[tool.poetry.group.test.dependencies]
pytest-asyncio = "^0.21"
httpx = "^0.25" # May conflict with aiohttp in dev group — separate group isolates it# Install only production dependencies (no dev groups)
poetry install --only main
# Install with a specific group
poetry install --with test
# Install without a specific group
poetry install --without devFix 5: Override a Transitive Dependency
When two packages require incompatible versions of a shared sub-dependency and you cannot upgrade either package, use overrides to force a specific version:
# pyproject.toml — force a specific version of a transitive dependency
[tool.poetry.dependencies]
python = "^3.11"
package-a = "^2.0"
package-b = "^3.0"
# Force urllib3 to a version compatible with both package-a and package-b
[tool.poetry.dependencies.urllib3]
version = "^1.26"
python = "*"For more complex overrides — use poetry source or direct path dependencies:
# Pin a transitive dep by adding it directly with a compatible range
[tool.poetry.dependencies]
urllib3 = ">=1.26.0,<3" # Explicitly manage the transitive deppoetry lock --no-update # Re-lock without upgrading other packages
poetry installFix 6: Use pip as a Fallback for Truly Incompatible Packages
When Poetry’s solver cannot find a solution but you know the packages actually work together at runtime, install one of them with pip directly inside the virtual environment:
# Activate the Poetry virtual environment
poetry shell
# Install the conflicting package with pip (bypasses Poetry's solver)
pip install some-problematic-package==1.2.3
# Return to normal Poetry workflow for everything else
exitWarning: Packages installed with
pipinside a Poetry environment are not tracked inpyproject.tomlorpoetry.lock. This is a last resort — document it clearly and investigate a proper fix. The dependency may break on the nextpoetry install.
Alternative — use a virtual environment directly:
python -m venv .venv
source .venv/bin/activate
pip install package-a package-b # No solver — just installsFix 7: Recreate the Lock File
If poetry.lock is out of sync or corrupted:
# Delete and regenerate the lock file
rm poetry.lock
poetry lock
# Then install
poetry installIf a specific package version was yanked from PyPI:
# Find what version is in the lock file
grep -A5 "name = \"pandas\"" poetry.lock
# Force update to a non-yanked version
poetry add pandas@^2.0 # Specify a valid version range
# Or update just that package
poetry update pandasMigrate from older Poetry versions (1.x to 1.5+/2.x):
# Poetry 2.x changed pyproject.toml format — update the project
poetry self update
# After updating Poetry, re-lock
rm poetry.lock
poetry lock
poetry installStill Not Working?
Try --verbose to see the full solver trace:
poetry add some-package -vvv 2>&1 | head -100Check if the conflict is in dev dependencies only. If production works but dev doesn’t, move the conflicting tool to an isolated group.
Check Python version compatibility. Some packages drop support for older Python versions in their latest releases:
# Require Python 3.11+ if needed packages require it
[tool.poetry.dependencies]
python = "^3.11"# Check which Python versions a package supports
pip index versions some-package # Check available versions
pip show some-package # After install — shows requires-pythonUse poetry env info to verify which Python and virtual environment Poetry is using:
poetry env info
# Shows Python version, virtual env path, and active status
poetry env list # List all environments for this project
poetry env use python3.11 # Switch Python versionCheck whether a private index is masking a public version. With Poetry 1.5+‘s source priority system, a primary source overrides PyPI. If your private mirror only carries an older version of a package, the solver will silently pick that older version and report a conflict against the newer constraints. Verify with poetry config repositories and confirm the priority of each source matches what you expect.
Check that poetry lock is not being run on a stale pyproject.toml. A common workflow bug is editing pyproject.toml, running poetry install without re-locking, and watching the install pull the old constraints from the lock. Run poetry lock --no-update after every manual edit to pyproject.toml, then poetry install.
Check the platform markers on transitive deps. Some packages declare python_version or sys_platform markers that cause the solver to require a version that doesn’t exist for your platform. poetry show --tree will show the markers — if a sub-dependency lists (python_version < "3.10") and you target 3.11, the solver may have nothing to install. Bump the minimum Python in pyproject.toml or pick a package that supports your target.
For related Python environment and package issues, see Fix: pip No Matching Distribution Found, Fix: Python ModuleNotFoundError (venv), Fix: pip Externally-Managed-Environment, and Fix: pip Could Not Build Wheels.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: uv Not Working — Command Not Found, Python Version Error, and Lock File Conflicts
How to fix uv errors — uv command not found after install, no Python interpreter found, uv run vs activate confusion, uv.lock merge conflicts, uv pip vs uv add, migrating from pip and Poetry, and workspace resolution failures.
Fix: Python venv Using Wrong Python Version
How to fix Python virtual environments using the wrong Python version — venv picking system Python instead of pyenv, specifying the interpreter path, and verifying the active environment.
Fix: mise Not Working — Shell Activation, .tool-versions, Plugin Install, and Python venv
How to fix mise (formerly rtx) errors — activation hook not running, tool not found after install, .tool-versions vs .mise.toml, Python venv integration, idiomatic env loading, and trust prompts.
Fix: joblib Not Working — Parallel Backends, Memory Cache, and Pickling Errors
How to fix joblib errors — Parallel n_jobs slower than expected, Memory cache miss, backend loky vs threading vs multiprocessing, pickling lambda not supported, dump load file size, and pytest interference.