Step-by-Step guide to upgrade Drupal 9 to Drupal 10

05 / Mar / 2024 by Ushma Gupta 0 comments

The process of upgrading a Drupal Project from 9 to 10 can be a bit of a challenging task. This blog covers the basic guidelines that will help you to upgrade major versions of simple or complex projects.

  1. Check for pre-requisites

  Platform requirements: 

 Drupal 10 requires PHP 8.1+. These platform updates must be done before starting the upgrade process. Here is the overview of full requirements for php, server, database etc –     

 Drush version:

 If you have Drush installed, you must check the recommended version. Drupal 10 requires drush 11 or later. Following is the command you can follow to install Drush 11  – 

 composer require 'drush/drush:^11' -W

 TIP: Some developers prefer to remove it temporarily and reinstall it later.

   2. Preparation for the D10 upgrade

 Install Upgrade Status module

This provides a good overview of the site’s upgrade health and helps to check the deprecations and compatibility of contrib modules/projects. Following are the commands to install and enable this module:

composer require 'drupal/upgrade_status:^4.1'
drush en upgrade_status

Review the report at page – /admin/reports/upgrade-status

Update the entire site (core and contrib modules) to the latest version of 9.4 or, at best 9.5.

You can manually edit the composer.json file and update the version for Drupal/core-* packages to recommended version (eg 9.5.11) and then run the following command to update all modules to their latest d9 release – 

composer update --with-all-dependencies
drush updb
drush cr


Now ensure that the site is working properly.

 Deal with all the deprecated modules or themes being used in your site.

      Core Modules removed from d10 are –

  • Aggregator
  • CKEditor (CKEditor5 now)
  • Color
  • HAL
  • Quick Edit
  • RDF

      Core Themes removed from D10 are –

  • Bartik
  • Classy
  • Seven
  • Stable

There are three options to deal with these: – 

Option 1. Simply uninstall it if not of any use on your site. 

Option 2. Switch to the different supported projects if available in core. E.g. change Bartik to Olivero, seven to Claro, ckeditor to ckeditor5

Option 3. If you can’t uninstall/switch, Install the corresponding contributed version from

E.g. If you have a custom or contributed theme that depends on classy(removed from d10 core), install the contributed Classy theme with Composer:

composer require “drupal/classy:^1.0”

CKEditor migration from 4 to 5

  • Turn on CKEditor5.
  • Ensure that your CKEditor plugins have CKEditor 5 versions (or remove those that don’t)
  • Navigate to Content Authoring> Text Formats and Editors using the admin menu. In the column Text Editor, you can tell which text formats use CKEditor.
  • For each text format that uses CKEditor, select Configure. Under Text editor, select CKEditor You can see status messages letting you know what has changed.
  • Do the above steps for all the text formats using CKEditor.
  • Check that CKEditor 5 is working ok and uninstall CKEditor.

Deal with the “Remove” section on the Upgrade status page (/admin/reports/upgrade-status).

To remove uninstalled modules/themes, simply remove their entries from composer.json file and run the composer update, OR you can run the composer remove command for each.

Note: If this list has some module/theme that is absent in composer.json, then you will need to remove it manually from the filesystem.

Deal with the “Update” section on the Upgrade status page.

Ensure all the contrib modules/themes/profiles are at the latest D10 stable release. Simply run the composer require command to fetch the latest version of the D10 stable release. Eg:-

composer require 'drupal/acquia_search:^3.1' -W 

Once this step is repeated for all the modules here and scanned again, nothing will be left in this section.

Deal with the modules in “Collaborate with maintainer” section with no D10 compatible release available on

  • Ensure from the project page that this is the latest D10-compatible version module. If not, run composer require & drush updb.
  • Otherwise, Lookout for a patch in the issue queue for D10 compatibility or create your own patch. Install cweagans plugin and add a compatibility patch in composer.json. 
composer require cweagans/composer-patches

Install the composer lenient plugin and add the patched module to the allowed list so that the composer can accommodate it for the D10 upgrade.

For this, run the install command and specify the required module (eg drush_delete):- 

composer require mglaman/composer-drupal-lenient
composer config --merge --json extra.drupal-lenient.allowed-list '["drupal/drush_delete"]

After running the above commands, the lenient section will be added in composer.json :-

Tip: Be sure you have added ALL patched modules to composer-drupal-lenient. If you miss even one, the composer will skip all of your requests for leniency, which can be very confusing.

Deal with the modules which don’t have a single release compatible with both D9 & D10 

To resolve this, Composer require both versions required by D9 as well as D10 to allow the module to be automatically upgraded when you upgrade Drupal core. Eg- 

composer require drupal/csv_serialization:^3.0 || ^4.0

  Update custom modules & themes in the “Scan” section

  • Update the version requirement in info.yml file of all these modules for D10 compatibility. 
Change from 
core_version_requirement: ^9
core_version_requirement: ^9 || ^10
  • Scan all items and resolve the deprecation errors either manually as per the suggestions or using the Drupal rector plugin.

To minimize the manual efforts, install the rector plugin for automatic fixing of deprecated code: 

composer require --dev palantirnet/drupal-rector
cp vendor/palantirnet/drupal-rector/rector.php .
vendor/bin/rector process modules/custom/[MODULE/THEME_NAME] --dry-run

Note: Run without “–dry-run” once you have looked into what changes would be made.

3. Start the D10 upgrade

By now, the site should be ready for the D10 update. You can verify this from the readiness percentage shown on the Upgrade status page.

  • Edit composer.json file and update the version for Drupal/core-* packages to ^10 (or any specific D10 version you want Eg 10.1.8).

  • Test the update before performing the actual update:
composer update --with-all-dependencies --dry-run

  • If it fails, run the following command to check for dependencies prohibiting the upgrade:
composer why-not drupal/core ^10 OR composer update "drupal/core:^10" -W --dry-run

Once the issue is identified, resolve it and again run the test update command until it runs successfully.

  • Run the actual update without dry run flag, run database updates, and clear the cache.
composer update --with-all-dependencies 
drush updb
drush cr

And the site is now fully upgraded to the Drupal 10 version !!

Patch verification.

Verify that all old patches added in composer.json file have been applied successfully.

Remove jquery dependency on once as it is removed from the D10 core.

Find every call of jquery.once() in custom modules/themes and update it with the new javascript once function.

Alos if you have any dependency on core/jquery.once library in your libraries.yml file, switch it with the core/once library.

Tip: Turn off the aggregation first if it’s enabled before doing this step.

Test the entire website

Check all the features and ensure the site is working properly. On every page load in the browser, look at Drupal logs for errors and/or warnings. Also, look in the browser console for any errors. Fix them as needed.

Some Common php errors faced due to incompatible php code:

  • ->accessCheck() must now be explicitly specified while using content entity query.
  • Twig output using {% spaceless %} is changed to {% apply spaceless %}.
  • Support for the “if” clause removed from “for” statements in twig files.
  • Test setUp() methods need a void return type (i.e. protected function setUp(): void

Fix these issues as per the suggestions in change records.

Some issues faced during the upgrade process: 

  1. If composer update results in error, “Your requirements could not be resolved to an installable set of packages.”. There can be two reasons for this:-
  • One or more of your contributed modules isn’t D10 compatible. To resolve this, Identify the culprit module in the composer error, visit the project page, look for the latest D10 stable release, and install it. Eg
composer require drupal/MODULE_NAME:^2.0.0-rc1 --no-update
  • Some of your project dependencies are not up-to-date to their latest version for core updates. To resolve this, follow the steps here.

      2. Some utilities like Drupal console or drush might hinder the core upgrade process. To resolve this, you can remove it altogether before the update and reinstall after the update. Eg

composer remove drupal/console --no-update
composer remove drush/drush --no-update

      3. If you use the module Advagg, entire JS might break on your site after the D10 upgrade.

One of the possible reasons is using Jsqueeze for minifying JS. Switch it to Jshrink or another mode as Jsqueeze is abandoned now.


Through this blog, we learnt how to make things D10 compatible while still using Drupal 9.  This included examining custom and contributed modules for compatibility. Once everything is ready, we upgraded the Drupal core. We also shared a few common problems faced during the upgrade and their solutions.

Hope that now you don’t find this process that tough next time. Check out our other blog posts for more insights.


Leave a Reply

Your email address will not be published. Required fields are marked *