Updating drupal/core with Composer - but Drupal core doesn't update

For the past two minor release Drupal core upgrades, I've had major problems trying to get some of my Composer-based Drupal codebases upgraded. For both 8.3.x to 8.4.0, and now 8.4.x to 8.5.0, I've had the following issue:

  1. I have the version constraint for drupal/core set to ~8.0 or ~8.4 in my composer.json.
  2. I run composer update drupal/core --with-dependencies (as recommended in Drupal.org's Composer documentation).
  3. Composer does its thing.
  4. A few things get updated... but not drupal/core. It remains stubbornly on the previous minor release.

Looking around the web, it seems this is a very common problem, and a lot of people soon go for the nuclear (or thermonuclear1) option:

  1. Run composer update (updating everything in the entire project, contrib modules, core, other dependencies, etc.).
  2. Profit?

This works, but it's definitely not ideal. If you have a site that uses a number of contrib modules, and maybe even depends on some of their APIs in custom code or in a custom theme... you don't want to be upgrading core and all contrib modules all in one go. You want to update each thing independently so you can test and make sure things don't break.

So, I was searching around for 'how do I figure out why updating something with Composer doesn't update that thing?', and I got a few good answers. The most important is the command composer prohibits.

Use composer prohibits to figure out what's blocking an update

composer prohibits allows you to see exactly what is preventing a package from being updated. For example, on this codebase, I know I want to end up with drupal/core:8.5.0, so I can run:

composer prohibits drupal/core:8.5.0

This gave me a list of a ton of different Symfony components that seemed to be holding back the upgrade, for example:

drupal/core                     8.5.0       requires          symfony/class-loader (~3.4.0)
drupal-composer/drupal-project  dev-master  does not require  symfony/class-loader (but v3.2.14 is installed)
drupal/core                     8.5.0       requires          symfony/console (~3.4.0)
drupal-composer/drupal-project  dev-master  does not require  symfony/console (but v3.2.14 is installed)
drupal/core                     8.5.0       requires          symfony/dependency-injection (~3.4.0)
...

Add any blocking dependencies to composer update

So, knowing this, one quick way I can get around this problem is to include symfony/* to update the symfony components at the same time as drupal/core:

composer update drupal/core symfony/* --with-dependencies

Unfortunately, it's more difficult to figure out which dependencies exactly are blocking the update. You'd think all of the ones listed by composer prohibits are blocking the upgrade, but as it turns out, only the symfony/config dependency (which is a dependency of Drush and/or Drupal Console, but not Drupal core) was blocking the upgrade on this particular site!

I learned a bit following the discussion in the Drupal.org issue composer fail to upgrade from 8.4.4 to 8.5.0-alpha1, and I also contributed a new answer to the Drupal Answers question Updating packages with composer and knowing what to update. Finally, I updated the Drupal.org documentation page Update core via Composer (option 4) and added a little bit of the information above in the troubleshooting section, because I'm certain I'm not the only one hitting these issues time and again, every time I try to upgrade Drupal core using Composer!


1 The thermonuclear option with Composer is to delete your vendor directory, delete your lock file, hand edit your composer.json with newer package versions, then basically start over from scratch. IMO, this is always a bad idea unless you feel safe upgrading all the things all the time (for some simple sites, this might not be the worst idea, but it still removes all the dependency management control you get when using Composer properly).

Comments

Here's my thermonuclear option:

I don't waste my time with composer update.

On dev environment I install Drupal 8 via composer, so I get a fresh copy of the latest codebase, then I install via composer all the modules I use on my production install.

I tar the whole shebang and untar it on my production install, after I've removed everything except “web/sites”, “web/themes” and eventually “web/libraries”.

In case there are custom modules or one with patches and spit, then I pull my whole production rig down to local and test it.

Ever since 8.1, my thermonuclear option is the only way to keep the few Drupal 8 sites tidy and without update issues.

Every-other-recommended/documented way been waste of time and I stopped early on and saved hours, days.

My Drupal 8 update option, takes 5 to 10 minutes per site.

I don't run hipster deploy as it's yet one more thing to maintain for - ain't gonna happen.
I wan't Drupal 8 to spit out html, css and maybe some js where needed, put Varnish in front and be done.

The hipster path to do Drupal 8 (or “modern” web deveopment) “the-right-way™” is nicely narrated story... but outside a few Drupal agencies and general web shops..., no sane person should be subject to such nonsense - ever.

Composer might've been well intended tool but in the context of Drupal, has been tragicomedy and I don't see things change for the better anytime soon.

We can argue all day about how Drupal 8 is adopted by bigger sites these days and not much by lesser ones and hence the adoption rate or lack thereof - nonsense!

Symfony and Object-Oriented programming in particular, is a really bad fit for Drupal in 99% of the cases and you will be seeing people running away from Drupal by the millions, when time comes to cut Drupal 7 from security releases.

OO programming complexity is the ultimate antithesis of Drupal 1 to 7 and it shows in Drupal 8.
10 years ago Drupal was capable of making hard things easy for the majority of it's users.

Drupal 8 helped some OO lunatics to pee in their pants out of joy cause now they can attempt some twisted, unpopular use-cases but for everyone else dealing with Drupal 8, even easy things - like updating Drupal core - became harder.

Drupal 8 might be argued as the better “system” by 100 or say 1000 OO nerds but the cost is - and will be - loosing millions of users, clients, sites...

Next week's security updates echoes vendor lock-in with absolute certainty - all Drupal shops with seats on the security team got their client's rigs patched for the vulnerabilities and on March 28 2018, everyone who is not hosted by Acquia, Pantheon, etc. will get the free update.

Was it not the case in 2014???

I appreciate your cynicism and echo your sentiments. Composer is just pure trash. Go back to using Drush and your problems will disappear. :)

Yep, it's how I roll for simple sites, composer got the require lines for the modules I add and the rest are stock stanzas.
Essentially, about 10 to 15 contrib and 1 or 2 custom modules, 1 custom theme without base theme and buncha sys css library override.

The problem with Drupal 8 and OO is simply PHP itself. PHP didn't start off as a language like Java where OO was standard practice. I won't even go into the problems with PHP built-in functions and general quirks which makes PHP as a functional language confusing and illogical sometimes.
In terms of Drupal 8 itself, I think what people are struggling with is Symfony and it's standards. Symfony is a major time saver when it comes to creating websites. The Drupal framework sitting on top adds complexity, but it's yet another Symfony implementation that you might find out in the wild.
Depending on your field of work, defaulting to functional PHP usage might work for you but you aren't doing yourself any favours by using some of PHP's capabilities. Learning OO is crucial even if you aren't a fan of OO from a theoretical perspective. You will save a lot of time when picking up existing projects and being able to understand what is going on.
I think the frustrations of Drupal 8 lies in a demographic of developers lacking understanding of fundamental OO programming concepts and the denial of it being a legitimate solution to problems and the refusal to learn PHP and programming theory in its entirety.
For example I wouldn't complain about advanced Clojure methodology because I didn't understand it and thought it was more of a hassle now that a Clojure based framework that I like is now using it. Once you learn, the problem becomes not with the language, framework or toolkit, but the implemented program.

You have made some valid points and put into words many thoughts I have about Drupal 8. The most important being the flight that end of life on D7 will likely cause. That makes me very nervous about my future prospects after sinking years into learning and keeping up with Drupal.

When Drupal 8.4.0 was released, I posted my own notes on the upgrade process: https://www.isovera.com/blog/upgrading-drupal-840-and-drush-9-composer

A couple of days ago, I upgraded a site from 8.3.7 to 8.5.0 (hoping to do a quick and easy update to 8.5.1 when it is released on Match 28). This time around, I found this StackOverflow page, which points the blame at the "composer merge" plugin. I have not done anything yet to verify that diagnosis, nor have I figured out the best way to work around the problem: https://stackoverflow.com/questions/43188197/composer-update-package-na…

Thank God I have not wasted time trying to install or use Drupal 8 for production. Installed it once for benchmarking and it turned out to be 3x times slower than Drupal 7 for authenticated users, thanks to all needless OOP complexity.

I am still working with Drupal 7 and use newer frameworks and technologies which provide ease of use / easy coding with performance that is 10x times faster than Drupal 7.

I think you meant:

"I am still working with Drupal 7 and use newer frameworks and technologies which provide ease of use / easy coding with performance that is 10x times faster than Drupal 8."

Yes, this!!! Thanks Jeff :-)

I've been using 'composer why-not', which I believe is an alias for 'composer prohibits', but I find it easier to remember.

In case anyone runs into this error on running composer update with symfony/*: "zsh: no matches found: symfony/*", and needs the help -- you need to escape the asterisk because zsh will be interpreting it differently. So run:

composer update drupal/core symfony/\* --with-dependencies

I have very similar issue to what Jeff describes:

composer prohibits drupal/core:8.5.0
drupal/core    8.5.0                            requires          symfony/class-loader (~3.4.0)
drupal/drupal  850.9999999.9999999.9999999-dev  requires          symfony/class-loader (~3.2.8)
drupal/core    8.5.0                            requires          symfony/console (~3.4.0)
drupal/drupal  850.9999999.9999999.9999999-dev  requires          symfony/console (~3.2.8)
drupal/core    8.5.0                            requires          symfony/dependency-injection (~3.4.0)
drupal/drupal  850.9999999.9999999.9999999-dev  requires          symfony/dependency-injection (~3.2.8)
... blah, blah, blah ...
drupal/core    8.5.0                            requires          twig/twig (^1.35.0)
drupal/drupal  850.9999999.9999999.9999999-dev  does not require  twig/twig (but v1.32.0 is installed)

But neither this:

composer update drupal/core symfony/* --with-dependencies

nor this:

composer update drupal/core symfony/\* --with-dependencies

worked for me (I use zsh), see below.

The nuclear option works, delete /vendor folder, but then I lose /vendor stuff for modules, so need to do compose update to get that stuff back.

Your requirements could not be resolved to an installable set of packages.
  Problem 1
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[3.2.x-dev].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.10].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.11].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.12].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.13].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.14].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.8].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.9].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.8].
    - symfony/yaml 3.4.x-dev conflicts with symfony/console[v3.2.8].
    - drupal/core 8.5.0 requires symfony/yaml ~3.4.5 -> satisfiable by symfony/yaml[3.4.x-dev].
    - Installation request for drupal/core 8.5.0 -> satisfiable by drupal/core[8.5.0].
    - Installation request for symfony/console ~3.2.8 -> satisfiable by symfony/console[3.2.x-dev, v3.2.10, v3.2.11, v3.2.12, v3.2.13, v3.2.14, v3.2.8, v3.2.9].

Regarding zsh error, I went ahead and just wrapped `symfony/*` in quotes so the command would look like this:

composer update drupal/core "symfony/*" --with-dependencies

Well I think we shouldn't start the next discussion about pro/cons of D8 and OOP. From my point of view OOP is not the problem but for example composer is an example where developers are left with an unfinished and bad integrated solution. That makes D8 harder. It has to become more simple but not from coding - that's OK even with OOP but for administration.

Regarding this blog post: In my case I just had to delete the core/composer.json to make composer update work well for core.

For what it's worth, I've been using composer to install drupal since 2014ish with Drupal 7. One of the things I've found as I work in support is that locking down the versions of modules and core is a good idea so that you CAN thermonuke the thing when you want becuase there are times when some of the various plugins even don't want to behave correctly. Patches for example... and it's so easy just to kill the vendor directory and let it go to town... In this cause `composer update` then doesn't do a mass upgrade... and it also gives you the ability to actually test out versions...

In a perfect world, we would report the versions of modules that doen't work with specific versions of core and the dependencies of those would be updated correctly and rereleased.

Definitely a valid approach. Control versions for core and modules strictly, then let Composer just mange the sub-dependencies.

I had a situation just this week where Composer did nothing as well (#4 above).

To get Drupal Core to update I had to move drupal/core from the "replace" section to the "require" section in composer.json, something like:

"require": {
"drupal/core": "^8.4"
[...]
},
"replace": {

},

and then rerun:

composer update drupal/core --with-dependencies

All good.

Same here, that worked for me also. I was not sure if that was "OK" or not, but it worked and was told in a Slack channel somewhere that this is OK to do. I tried to understand the diff between require and replace but could not figure it out.
Man, which is the "right" solution here? And sometimes you delete the vendor folder and sometimes not?
I agree with comment from above:
".... composer is an example where developers are left with an unfinished and bad integrated solution. That makes D8 harder."
Drupal 8: 1) OOPHP is a learning curve, but seems the right way to go - look at Symfony, Laravel, etc. 2) Twig is great. 3) Config is great. 4) But Composer in Drupal is a mess.
Thanks Jeff for all your great blog posts on this.

Rick,
Replace in composer is a little tricky to figure out. Essentially, it is saying that your current project is supposed to replace "drupal/core". So anything that depends on drupal/core, instead of going to the composer repo to find drupal/core, it will look directly at your project since that is now considered drupal/core. That may not have helped clear it up, but I do think this one blog post is pretty good at explaining it, and the diagrams help: http://www.darwinbiler.com/how-does-the-replace-property-work-in-compos…

Also, I have typically moved drupal/core into the require section.

Barrett

You you so much ! Great explanation.

Hours of wasted time trying to get Drupal updated. Time to move on from this CMS.

Thanks for this tip - I used this info more than one time: composer update drupal/core symfony/* --with-dependencies

Nice Jeff...
I ran into this issue updating drupal/core (8.5.1 => 8.5.3)

My issue turned out to be:
webflo/drupal-core-require-dev 8.5.1 requires drupal/core (8.5.1)

Using the following did the trick...
composer update drupal/core webflo/* --with-dependencies

I read it's recommended to use Composer to manage Drupal dependencies anyway, as "Drush 9 no longer supports updating Drupal and leaves the work to composer." I'm currently using Drush 9.2.3.

Thank you! I had this same issue when updating drupal/core to 8.5.5, running composer update drupal/core webflo/* --with-dependencies solved it.

Thanks for this. After dealing with a lot of these same hassles, my thermonuclear option (using D8 for multisite) has become:

1. create a separate web root beside the current one
2. copy composer.json from the current web root to the new one, and make any necessary adjustments by hand (e.g. "^8.4" to "^8.5")
3. run "composer install" in the new root
4. copy or move site directories over one at a time, updating the Apache config to point to the new root

So far, so good, but if there's any reason why this might be a terrible idea, I'm always open to advice :-)

Just ran into this again with my Raspberry Pi Dramble codebase—it would upgrade to 8.5.7, but no further. When I ran prohibits, I get:

$ composer prohibits drupal/core:8.6.0
drupal-composer/drupal-project  dev-master  requires  drupal/core (~8.5.3) 
webflo/drupal-core-require-dev  8.5.7       requires  drupal/core (8.5.7)

I then found the issue: Update composer.json to require latest stable version of Drupal, which changes the drupal/core requirement from ~8.5.3 (which doesn't allow a minor release upgrade, so it would only go up to 8.5.x and never to 8.6.x) to ^8.6.0, which allows minor release upgrades.

I changed those two values in my composer.json, then ran composer update again, and now I have Drupal 8.6.0 installed.

Thanks so much Jeff. I'd tried evreything to no avail till I read your above comment. I had same issue drupal core not updating past 8.5.7 and now done great.

Same here and thanks! This issue had me in a few rabbit holes including attempt of installing composerize module, but in the end, simply running composer prohibits is what really pointed to what to solve.