Composer stuck at Something's changed looking at all rules again
While upgrading one of my laravel application from version 5.3 to 5.4, I came across a weird situation which was coming from composer dependency management. The situation was that when running composer install it was getting stuck at Something's changed looking at all rules again(1)
and composer was showing counter of attempts in brackets which was increasing from 1 to 900+. It took arund 2+ hours composer update was stuck in this situation and attempts counter was increasing, even when the system where application was hosted had pretty good configurations.
- How do I get this information :
When you run composer command, lets say composer install
, it does internal steps it's supposed to do one by one. However, we just see the high level output in command promt and not the details of steps. Similarly, the error message I saw can not be seen directly if you just do composer install
. You need to make the output more verbose by passing -v
command line argument. You can pass upto 3 v's to get more verbosity
For e.g. :
`composer install -vvv`
When I did this, I got lot of detailed steps whats composer is doing internally, one of these verbose messages was the error message Something's changed looking at all rules again(1)
- Why composer gets stuck :
Okay, to explain it's comparatively easy to understand why it gets stuck. Let's take an example that application has 2 packages techsemicolon/package-first
and techsemicolon/package-second
:
"require": {
"php": ">=5.6.4",
"techsemicolon/package-first": "5.4.*",
"techsemicolon/package-second": "2.3.*",
.
.
.
.
}
Now the both these packages have package techsemicolon/dependency-package
in their own dependencies. But
`techsemicolon/package-first` requires `techsemicolon/dependency-package` at version `2.*.*`
`techsemicolon/package-second` requires `techsemicolon/dependency-package` at version `3.*.*`.
Now, it's really confusing for composer to now decide if it should install the techsemicolon/dependency-package
at version 2.*.*
or 3.*.*
. When we do composer install or update, it calculates these dependency trees and decide which version to install/update to. It checks the dependency rules defined in composer.json
of application as well as those in individual package as their dependencies. Hence it gets stuck at Something's changed looking at all rules again
.
Now, there can be situation where it recalculatues the rules again and shows this message but within a minute or two it finds the version which can satisfy the dependencies and proceeds. But in cases like mine, it calculates the rules in circles and gets stuck for really really long time.
- The solution :
A note to start with, this is not the only or best solution to resolve this. But, considering this error is little different than commonly occuring composer errors, this is what I could do to resolve this quickly and effectively.
Let's consider your composer has 15 packages in
require
dependency section of your app's maincomposer.json
. I followed an approach which is very neive, I divided those 15 depencies into 3 sections of 5. I commented out first 5 and ran composer install. It if still gets stuck at error, then I commented out next 5 and uncommented first 5 and ran composer install again. I kept doing this until I found a faulty batch which if I comment out then composer install works properly. I kept composer install with verbosity of--vvv
so it shows detailed output.Then you will have n number of packages from the commented out batch, 5 in my case.
Then I went to
https://packagist.org
and went to each of that package from the faulty batch. I checked their internal dependencies or requirements of php version etc. Cross checked with other packages in the same batch if there is a conflict of version.But I still did not find the dependency conflict. So I came back to my app where composer install worked when I commented out the failty batch. Then I did
composer show --tree
. That time I found that :
`barryvdh/laravel-dompdf` required `dompdf/dompdf` at version `^0.8`
`laravel-datatables-oracle` required `dompdf/dompdf` at version `^0.7`
I had to upgrade version of laravel-datatables-oracle
so that its dependency of dompdf/dompdf
is at version ^0.8
which matches with barryvdh/laravel-dompdf
's installed version.
Don't worry, once you do this in your own app you will figure it out that it's not that hard. I freaked out myself when I saw the error for the first time.
- Quick note on composer diagnosis :
You can run composer diagnose
which gives you suggestions and warnings to improve the composer.json
package version calculations. e.g.
require.barryvdh/laravel-debugbar : exact version constraints (2.3.2) should be avoided if the package follows semantic versioning
require.webmozart/assert : exact version constraints (1.2) should be avoided if the package follows semantic versioning