Upgrade Drupal from 9 to 10

We needed to upgrade multiple Drupal sites from 9 to the last supported version, which at the moment I write this guide was the 10.2.1 version release. That is why I decided to share the upgrade path I used on sites of different sizes and complexities. I hope you find this guide useful.

Before performing the D10 upgrade

  1. Backup files and database before you release any of these changes prior to the actual Drupal 10 upgrade.
  2. Remove from Composer any module that isn’t installed, that will save you some time in steps 3 and 7.
  3. Uninstall or replace the deprecated modules. CKEditor 4 is a mandatory module to replace for the new CKEditor 5, follow the guide in the previous link and make sure all the custom extensions you have with this WYSIWYG editor are compatible with V5. Use this guide to upgrade to CKEditor 5.
  4. Uninstall or replace deprecated themes.
  5. Upgrade PHP 8.1.6 or higher (required).
  6. Upgrade Composer 2.3.6 or higher (required).
  7. If NGINX is used, the virtual host will need to be updated for static assets.
  8. Use Upgrade Status to check the compatibility of your custom modules and/or themes.
  9. Update all contributed modules to a compatible version for D10. Some modules claim to be ready for D10, but that isn’t entirely true.
  10. Review your custom (and any contrib module if needed) code with Rector.
    • Suggested workflow:
      • Analyze your code to get suggested changes: $ vendor/bin/rector process web/modules/[PATH_TO_YOUR_MODULE] –dry-run
      • Apply suggested changes: $ vendor/bin/rector process web/modules/[PATH_TO_YOUR_MODULE]
  11. Make sure your custom twig templates are compatible with Twig 3 (required).
  12. If your site uses jQuery.once, use the new library once() (required).
  13. Drupal 10 drops support for IE 11. If you website has users with that browser or a tool like wkhtmltopdf that parses pages, you will need to find a solution for this.

Update to Drupal 10

  1. Backup files and database before you release the Drupal 10 upgrade.
  2. Update the required versions of both the core-recommended and dev-dependencies packages. We use --no-update to avoid a chicken-and-egg problem with mutual dependencies (more info):
    • composer require 'drupal/core-recommended:^10' 'drupal/core-composer-scaffold:^10' 'drupal/core-project-message:^10' --no-update
  3. If you are planning to upgrade to Drupal 10.2.x or above, update to Drush 12. Drush versions below 12.4.3 are incompatible with Drupal 10.2.x
    • composer require 'drush/drush:^12' --no-update
  4. Test the update to the code itself with the --dry-run option:
    • composer update --dry-run
  5. If everything looks good in previous step
    • composer update
  6. If the update worked without any errors, confirm you can run the install command
    • composer install
  7.  run any pending database updates, in case a new version of a module needs to update the database with Drush
    • drush updatedb
  8. Export config changes
    • drush config-export
  9. Check the Drupal status page at /admin/reports/status to make sure all listed items are as expected.

After performing the D10 upgrade

  1. Visit the /admin/reports/dblog Logs page to check the latest entries. Alternatively use Drush drush watchdog:tail
  2. Start testing your website as a regular user. Make sure you don’t see any Javascript error while you test the site.
  3. Start testing your site as admin. make sure you are able to edit any content type, specially the ones that use CKEditor plugins. If your site uses Layout Builder or Paragraphs, this is the time to perform a regression test on those edit pages.

Common problems

“Your requirements could not be resolved to an installable set of packages” error from Composer:

Look in the error message which contrib/custom modules are being mentioned. Debugging Composer errors sometimes aren’t easy to deal with.

Composer patches do not re-apply:

Even if you are using cweagans’s composer-patches, you notice that patches aren’t applied when Composer is calculating the dependencies. Try installing Composer Drupal Lenient to deal with that problem.

Custom (or contrib) modules not compatible with Drupal 10:

Install Rector to speed up fixing deprecated Drupal code.

Upgrade Status page mentions the “Invalid permissions will trigger runtime exceptions in Drupal 10. Permissions should be defined in a permissions.yml file or a permission callback.” error:

On this Drupal change record you will find ways to solve this, and also a script that can be used if many permissions are listed to be fixed.

A Drupal service, hook, class stopped working in D10:

Take a look at the change records for Drupal core, the change you need might be listed here. These pages always provide good insight about what is required to update from a specific core version.


There are infinite combinations of Drupal setup using different infrastructure types, what worked on the sites we upgraded might not fully work on your site. If that is the case, feel free to leave a comment.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.