Resolving Composer Dependency Conflicts: A Step‑by‑Step Diagnostic Guide
When Composer aborts with 'Your requirements could not be resolved' the cause is often a version clash, platform mismatch, or replace/conflict confusion. Follow these checks to fix it.
15 Nov 2025, 04:34 UTC

Recognizable Condition
When you run composer update or composer require Composer aborts with:
Your requirements could not be resolved to an installable set of packages.
Conflict: ...
The conflict list shows the packages, the requested versions, and the derived constraints that cannot be satisfied.
Common Root Causes
| Cause | Typical Symptom |
|---|---|
| Direct version conflict | Two packages require incompatible versions of a shared dependency. |
| Platform requirement mismatch | Package requires a PHP extension or version not present in the runtime or config.platform. |
| Replace/Provide confusion | A package replaces another but the constraint chain still pulls the replaced package. |
| Stability restrictions | Global minimum-stability or prefer-stable settings block needed dev versions. |
| Repository priority | Private repo metadata lags behind Packagist, causing missing tags. |
Ordered Diagnostic Checks
-
Run
composer why-not <package> <version>to see the exact constraint chain that fails. -
Verify platform packages:
composer show --platformlists the PHP version and extensions Composer sees. -
Inspect
composer.lockfor pinned versions that may be forcing a conflict. -
Check the
replaceandprovidesections of the conflicting packages’composer.json(usecomposer show -t <package>). -
Test a relaxed stability: temporarily set
minimum-stability: devandprefer-stable: falsein the rootcomposer.jsonto see if the conflict disappears. -
Clear Composer’s cache and rerun with verbose output:
composer clear-cache && composer update -vvv. Search the output for the word "Conflict" to pinpoint the decision point.
Targeted Fixes
1. Direct Version Conflict
- Widen the version constraint in your
composer.json(e.g., change^1.2to~1.2.0). - If the conflict is in a transitive dependency, fork the package and adjust its
composer.json, then reference the fork via a VCS or path repository.
2. Platform Requirement Mismatch
- Install the missing PHP extension on the target machine.
- Or override the platform requirement in
composer.json:"config": { "platform": { "php": "8.3.0", "ext-swoole": "5.0.0" } } - Remember that
config.platformonly affects the resolver; the runtime must still provide the extension.
3. Replace/Provide Confusion
- Add a
conflictentry to your rootcomposer.jsonto suppress the replaced package:"conflict": { "vendor/old-package": "*" } - Alternatively, add a
replaceentry to your root to explicitly replace the problematic package.
4. Stability Restrictions
- Prefer per‑package stability flags:
"vendor/package": "@dev"instead of globalminimum-stabilitychanges. - Only relax
minimum-stabilitytemporarily for a targeted update (e.g.,composer update vendor/package --with-dependencies).
5. Repository Priority
- Run
composer show --all --available <package>to verify the latest tags in the private repo. - If the private repo is out of sync, bump the version or push the missing tag.
- As a last resort, remove the private repo entry and force a fresh install from Packagist, then re‑add the private repo with
--no-cache.
Escalation Criteria
If the resolver trace shows a cycle involving packages you do not control and none of the above fixes resolve the conflict, file an issue against the upstream maintainer. Attach the full composer why-not output and the composer show -t dependency tree. Provide a minimal composer.json that reproduces the error if possible.
Practical Engineering Decisions
- Use explicit version constraints (e.g.,
^1.2or1.2.*) instead of exact versions to allow safe upgrades. - Run
composer validate --strictin CI to catch schema or constraint errors early. - Commit
composer.lockto the repository to ensure reproducible installs. - Schedule
composer outdated --direct --strictweekly to detect drifting constraints before they break the resolver. - In CI environments, use
composer install --no-dev --dry-runafter any change to verify resolution without side effects. - Verify that the
composer.lockhash matches across environments by runninggit diff composer.lockor using a checksum tool.
Checking Your Fix
- Run
composer update --lockto generate a new lock file. - Execute
composer validate --strict --no-check-allto ensure the JSON is still valid. - Use
composer why <conflicting-package>to confirm the conflict chain no longer appears. - If
composer install --dry-runsucceeds, merge the changes into your main branch.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.