Note: This is a public page

Upgrading a Project to Drupal 10 can be a bit of a challenge. This covers my basic workflow that allowed me to update several fairly complex projects.

For obvious reasons, run this on a test/development environment, you will likely need to go back to make changes to your production site then first.

Drupal 9/10 is used as an example, and should be interchangeable with Drupal 10/11 in the future and so on.

The focus here is on composer itself, not custom modules and Drupal core compatibility of the actual code. Modules like upgrade_status help with that and likely also can warn you ahead of time about modules without a release, new major versions and so on.

1. Get the lenient composer plugin

This is only needed if there are contrib modules that do not yet have a Drupal 10 release. This can be skipped if that’s not the case, but if you’re not sure and reading this, you are likely in such a situation.

The plugin must be added first, while composer is still functional so that it’s code can act.

composer require mglaman/composer-drupal-lenient

2. Replace drupal/core-recommended with drupal/core

drupal/core-recommended is designed to ensure that you are using the exact same dependencies that Drupal core is tested against. However, the very large amount of indirect dependencies makes it very hard for composer to resolve dependencies and understand what exactly the problem is. It might for example produce very long list of incompatible versions.

It is in many cases possible to add it back at the end, although you might need to do another full composer update as composer will likely need to downgrade some dependencies again. You can do so with by hand with an editor in composer.json, or use composer remove/require —no-update. —no-update is just a CLI shorthand for making a manual change to composer.json without verifying it. Which is what you want to do for the several intermediate steps.

composer remove --no-update drupal/core-recommended
composer require --no-update drupal/core

3. Update all other drupal/core* packages to ^10.1

Don’t forget the drupal/core-dev dev requirement if you use that. This installs the development dependencies for drupal (core) development. This includes tooling like phpcs, phpstan, coder as well as phpunit and other dependencies required to run tests. If you don’t have phpunit tests that you run in your project or run automated coding standard checks similar to drupal core, consider removing this.

4. Run composer update, resolve problem, repeat

$ **composer update**
Gathering patches for root package.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires **drupal/ckeditor_templates** ^1.2 -> satisfiable by drupal/ckeditor_templates[1.2.0, 1.x-dev].
    - drupal/ckeditor_templates[1.2.0, ..., 1.x-dev] require drupal/core ^8 || ^9 -> found drupal/core[8.0.0-beta6, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev] but it conflicts with your root composer.json require (^
10.1).
  Problem 2
    - Root composer.json requires **drupal/tb_megamenu** ^1.0@beta -> satisfiable by drupal/tb_megamenu[1.0.0-beta1, ..., 1.7.0].
    - drupal/tb_megamenu[1.0.0-beta1, ..., 1.7.0] require drupal/core ^8 || ^9 -> found drupal/core[8.0.0-beta6, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev] but it conflicts with your root composer.json require (^10.
1).
  Problem 3
    - **drupal/node_revisions_autoclean** dev-1.x requires drupal/core ^8.7.7 || ^9.0 -> found drupal/core[8.7.7, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev] but it conflicts with your root composer.json require (^10.1).
    - drupal/node_revisions_autoclean 1.x-dev is an alias of drupal/node_revisions_autoclean dev-1.x and thus requires it to be installed too.
    - Root composer.json requires drupal/node_revisions_autoclean 1.x-dev@dev -> satisfiable by drupal/node_revisions_autoclean[1.x-dev (alias of dev-1.x)].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

First, identify the dependency/drupal module that has a conflict. That can be tricky, but without drupal/core-recommended, it should be much easier. The above is real output from an example composer.json that I recently worked with. See also the FAQ below for more examples and suggestions.

For each conflict, you have 3 options. Once some or all visible modules have been addressed, repeat composer update.