An issue has recently been arising with new Flarum installations and I want to give some guidance in how to solve it.
Identifying the issue
You might get an "Installation failed" from Composer when trying to install a new extension. The output of Composer will show some kind of conflict message which will include things like:
composer require fof/uploadUsing version ^0.10.0 for fof/upload
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Installation request for fof/upload ^0.10.0 -> satisfiable by fof/upload[0.10.0].
- Conclusion: remove guzzlehttp/guzzle 7.0.1
- Conclusion: don't install guzzlehttp/guzzle 7.0.1
- fof/upload 0.10.0 requires guzzlehttp/guzzle ^6.0 -> satisfiable by guzzlehttp/guzzle[6.0.0, 6.0.1, 6.0.2, 6.1.0, 6.1.1, 6.2.0, 6.2.1, 6.2.2, 6.2.3, 6.3.0, 6.3.1, 6.3.2, 6.3.3, 6.4.0, 6.4.1, 6.5.0, 6.5.1, 6.5.2, 6.5.3, 6.5.4, 6.5.5].
- Can only install one of: guzzlehttp/guzzle[6.0.0, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.0.1, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.0.2, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.1.0, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.1.1, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.2.0, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.2.1, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.2.2, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.2.3, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.3.0, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.3.1, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.3.2, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.3.3, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.4.0, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.4.1, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.5.0, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.5.1, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.5.2, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.5.3, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.5.4, 7.0.1].
- Can only install one of: guzzlehttp/guzzle[6.5.5, 7.0.1].
- Installation request for guzzlehttp/guzzle (locked at 7.0.1) -> satisfiable by guzzlehttp/guzzle[7.0.1].
Installation failed, reverting ./composer.json to its original content.
The cause
Composer lets each extension request the dependencies and dependencies versions of their choice. Not all extensions require the same dependency versions, and this can lead to conflicts.
In this case the conflict is actually solvable, but Composer is unable to solve it by itself.
The problem is that league/oauth2-client
works with either Guzzle ^6.0
or ^7.0
, while most other extensions work with only Guzzle ^6.0
.
If league/oauth2-client
is installed first, Composer will install version 7.0 of Guzzle. If you then try to install extensions that need Guzzle 6.0, Composer will not accept to downgrade the major version of an already-installed dependency.
league/oauth2-client
is installed as a dependency of the Facebook/GitHub login extensions, and probably other community extensions that provide login.
I think the issue does not affect everyone because there's usually one other extension installed by default that requires Guzzle 6 only. It's the Twitter login extension which relies on league/oauth1-client
which only works with Guzzle 6. So I believe everyone having this issue must have removed the Twitter login extension at some point, and then ran a global Composer update. Flarum core does not require Guzzle by the way.
It only started happening recently because the oauth2 client started allowing Guzzle since version 2.5.0 which was released on July 18 2020. Older Flarum installs which have not updated their extension's dependencies for a while still use version 2.4.* which doesn't create this conflict.
This issue can be found on Composer's issue tracker here and here. It sounds like it has been kind of solved in Composer v2, but I have not tested v2 yet.
The solution
Composer has optional command flags (like --update-with-dependencies
) to allow dependency updates but in Composer v1, this doesn't seem to allow major version downgrades. So here's the workaround:
Step 1: Install Guzzle ^6.0
as a direct dependency, this forces Composer to downgrade from major version 7 to 6:
composer require guzzlehttp/guzzle:^6.0
Composer will show something like "Downgrading guzzlehttp/guzzle (7.0.1 => 6.5.5)".
Step 2: Install the new package that couldn't be installed in the first place by following the instructions from the extension's discussion. For example for FoF Upload:
composer require fof/upload
Step 3: Remove the direct Guzzle dependency. This avoids potential other issues in the future:
composer remove guzzlehttp/guzzle
Composer will say "Nothing to install or update". That's expected. This will just remove the line about Guzzle from composer.json
. You could also manually remove that line but running the command ensures you don't break the formatting of composer.json
.