Drupal 9 to Drupal 10 Upgrades: Complete Technical Guide and Upgrade Steps

January 15, 2023

Upgrading Drupal 9 to 10 is straightforward but there are quite a few steps involved. Read below for a detailed technical breakdown of how to upgrade Drupal 9 to Drupal 10.

Before you begin: if you’re not looking to handle your own upgrade, contact us for a free Drupal 10 upgrade assessment.


1. Make sure your site is fully “composerized”, including core, by following the instructions at Converting a Drupal 8 or 9 site to Composer
2. Make sure you back up everything – code, files, database – before doing anything.
3. Be prepared to check your webserver log files. The error messages will help you find answers on Google to common upgrade problems.

Can I update from Drupal 8 to Drupal 10 directly?

No, you must go from Drupal 8 to Drupal 9, then you can upgrade to Drupal 10. You can read our detailed guide for upgrading Drupal 8 to Drupal 9 here.

First, upgrade to the latest Drupal 9 Core

1. Composer require the new Drupal version (shown here as 9.5)

composer require drupal/core-recommended:^9.5 --with-all-dependencies

2. Run updatedb:

drush updatedb

3. Clear the cache:

drush cache-rebuild

Upgrade your Drupal 9 Modules

1. Run composer update:

composer update

2. Run updatedb and clear cache:

drush updatedb
drush cache-rebuild

Prepare your Drupal 9 site for the Drupal 10 upgrade

1. Install and enable the upgrade status module in your D8 site:

composer require drupal/upgrade_status
drush pm-enable upgrade_status

If you get conflicts with the “phpstan-drupal” package, try the following command:

composer require drupal/upgrade_status mglaman/phpstan-drupal:^1.0 phpstan/phpstan:^1.0 phpstan/phpstan-deprecation-rules:^1.0 -W

There’s more information about the phpstan issue at this thread: Cannot update Upgrade Status due to locked phpstan-drupal dependency

2. Browse to /admin/reports/upgrade-status

  • If your PHP version is behind, you’ll need to ensure that your host supports PHP 8.1 and change your PHP version to 8.1.
    • On pantheon, you can simply edit your pantheon.yml file and change “php_version” to “8.1”
    • If using lando, you can update your appserver to use 8.1 by editing .lando.yml and adding the following under “services”:
type: php:8.1
  • For any modules in the “remove” section of the list (these are modules that aren’t actually enabled in your instance, simply remove them from composer.json and re-run composer update

BE CAREFUL that sometimes people name their features the same as the name of a module, e.g. “Block Visibility Groups”. Only remove from composer.json if the type is listed as “contributed”.

Note: there may be custom modules in this list that you need to remove from the filesystem manually, as they won’t be in composer.json.

  • For modules in the “update” section, update composer.json with the appropriate version number as indicated in the “drupal.org version” column. For example, if your “local version” of webform is 6.1 and the “drupal.org” version is 6.2, change the webform line in composer.json to: drupal/webform”: “^6.2” Then run composer update and drush updb . Repeat this step for all modules in the “update” section. After this step, you should have no modules left in the “update” section.

3. Go to the “scan” section and select all items

4. Scroll to the bottom and click “scan selected”
Note: Note: I’ve seen the scan error out but if you go back to the upgrade status page, everything is there. So if you get an error, check the upgrade status page to see if you have what you need anyway.

5. You’ll probably see a lot of custom modules with “1 warning” and it looks like this if you click on “1 warning”:

Add core_version_requirement: ^9 || ^10 to designate that the module is compatible with Drupal 10. See https://drupal.org/node/3070687.

All this means is that you have to edit the .info.yml for the module and change the “core_version_requirement” to “^9 || ^10”.

This script will automatically update the .info.yml files if you download it and run the following commands from your project root directory (this assumes your modules directory are in web/modules – change accordingly if your directory structure is different):

php update_module_core_version_to_10.php ./web/modules/custom
php update_module_core_version_to_10.php ./web/modules/features

6. Re-run the scan after completing the previous step. You should now have far fewer custom modules with problems.

7. For modules under “collaborate with maintainer”, first check that you’re on the latest version of the module. Check the .info.yml file against the latest version on the module’s project page on Drupal.org.  If you’re not on the latest version, composer require the latest version and run drush updb.

Otherwise, go to the module’s issue page and see if there is information and/or a patch for D9. Most will have something. If so, patch the module and re-run the scan.

8. For modules under “manually fix”:

  • Click the “X Problems Reported” link. Some of the instructions will be extremely straightforward. Where the instructions are clear, edit the module code per the instruction.
  • If the problem is just a deprecation warning that does not say that it has been removed in Drupal 9, you may be able to ignore it for now. Try to fix it using the next steps below, but it may be OK to leave it in in the absence of a fix.
  • If the problem is not yet documented, you’ll have to go to Google. Search for the error message (don’t include and line numbers or directory names that will be specific to your own environment) and see if there is a Drupal.org thread detailing how to fix the problem. Sometimes it helps to look at .patch files that have been created – you can usually see the line that was removed and the line that was added.

9. Run updatedb: drush updatedb

10. Manually compare your .htaccess files and robots.txt files from the original D8 copy of the site. These are likely to get overwritten in the upgrade, so make sure no customizations in the original htaccess or robots.txt files were removed.

If you are getting 500 internal server errors or PHP errors after the upgrade

Most likely, there are custom modules that have incompatible calls to Drupal’s internal code/API. These need to be updated. Thankfully, there is a tool called rector that can identify and fix these issues for you automatically.

Using rector for a Drupal 10 upgrade

1. First install rector by running the following command:

composer require --dev palantirnet/drupal-rector

2. Copy the rector config to the document root:

cp vendor/palantirnet/drupal-rector/rector.php .

3. Do a dry run to see what changes would be made to the module:

vendor/bin/rector process web/modules/custom/YOUR_MODULE_NAME_HERE --dry-run

4. Apply the suggested changes:

vendor/bin/rector process web/modules/custom/YOUR_MODULE_NAME_HERE

You can find more information about rector on the rector github page.

Need help upgrading Drupal 9 to Drupal 10? Contact us today for a free consultatio and estimate!