TL;DR: Composer is telling you two version constraints cannot both be true, but the raw output is hard to read. Run composer why-not on the package you want to find the single blocking requirement. Relax or upgrade the blocker in composer.json, then update the package together with its blockers. Verify with composer validate and a fresh install.

## The error

```text
"composer update: Your requirements could not be resolved to an installable set of packages"  -  how to fix
```

## Steps to fix

1. Ask composer directly what blocks you: composer why-not vendor/package 2.0 (replace with the real package and target version).
   Expected: Composer prints the blocking chain, for example vendor/other 1.5 requires vendor/package below 2.0.

2. Check the other direction too: composer prohibits vendor/package 2.0 shows everything currently installed that forbids that version.
   Expected: You see the full set of installed packages incompatible with the target.

3. See if the blocker has a newer release supporting your target: composer show vendor/other --all | grep versions, or check packagist.
   Expected: You know whether upgrading the blocker unblocks you.

4. Edit composer.json to widen the blocker's constraint (or require its newer major), then run composer update vendor/package vendor/other --with-all-dependencies.
   Expected: Composer resolves and rewrites composer.lock without the installable set error.

5. Run composer validate and composer install --dry-run (or a clean install in CI).
   Expected: Validate reports the file is valid and the install completes; then run the test suite.

## Use this when

- composer update or composer install fails with requirements could not be resolved to an installable set
- A PHP dependency upgrade is blocked and the raw composer output is too long to parse
- An agent's upgrade PR needs the manual composer conflict procedure

## Not for this skill when

- Composer memory-exhausted crashes, which are resource problems (raise the PHP memory limit)
- Authentication failures against private packagist or satis repos
- Platform requirement failures (php version, ext-missing), which name the missing extension instead

## Variant phrasings

- composer update your requirements could not be resolved
- composer why-not shows nothing but update still fails
- Root composer.json requires X, found Y but it does not match

## Why it happens

Composer solves the whole dependency graph as a SAT problem: every require line in composer.json and every dependency of every package must hold simultaneously. When two constraints on the same package are mutually exclusive there is no valid set, and Composer reports the failure. why-not and prohibits exist because the raw solver trace is unreadable; they re-run the solver scoped to one package so the blocking edge stands out.

## Edge cases

- Do not use --with-all-dependencies blindly on a large monorepo; scope the update to the package and its blockers to avoid surprise majors.
- Minimum-stability settings can hide valid candidates; check that stability flags match the versions you expect.
- If the blocker is abandoned, replace it or fork it rather than pinning ancient versions forever.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_n9rfKKvmoEMLMBMCVrCmPw
