Guide to Upgrading Drupal 8 to Drupal 9

April 14, 2022

Prerequisites
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. It will save you a LOT of time, as fixes for many errors are probably already outlined below under “Drupal 8 Upgrades: Common Errors”

First, upgrade to the latest Drupal 8 Core

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

composer require drupal/core-recommended:^8.9

2. Run updatedb:

drush updatedb

3. Clear the cache:

drush cache-rebuild

Upgrade your Drupal 8 Modules

1. Run composer update:

composer update

2. Run updatedb and clear cache:

drush updatedb
drush cache-rebuild

3. If the media_entity module is installed and its version is < 2.0, run the following commands. Otherwise, skip this step.

composer require drupal/media_entity:^2.0
composer require drupal/media_entity_browser:^2.0
drush updb

If you cannot install using composer or encounter other issues, see:
https://www.drupal.org/docs/8/core/modules/media/faq-transition-from-media-entity-to-media-in-core#upgrade-instructions-from-media-entity-contrib-to-media-in-core

4. Browse to the “update” page at /admin/modules/update and see if there are modules that still need to be updated.

5. If modules are still listed, locate their entry in composer.json and follow the steps below:

  • If the module has an explicit version number (one that doesn’t start with ~ or ^), you may need to add a ^ at the beginning of the module version. For example: Change drupal/module_filter”: “3.1.0” to drupal/module_filter”: “^3.1.0” , then run composer update

Note that there may be a reason that someone set the module version explicitly. You’ll need to check for any project docs or with the original developer (if possible) to determine if there’s still a reason a module needs to live at a specific version. If you can’t determine, try upgrading and then thoroughly test the module’s functionality.

  • If the module is set to a different major version, you may need to bump it to a new major version. For example: Change “drupal/simple_sitemap”: “^2.0” to “drupal/simple_sitemap”: “^3.0”, then run composer update

(Note: alpha and beta modules may need to be represented like this: 8.x-5.0-alpha8)

6. If you’ve run composer update again, be sure to run updatedb and clear the cache:

drush updatedb
drush cache-rebuild

Start the Drupal 9 Upgrade

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

composer require drupal/upgrade_status
drush pm-enable upgrade_status

2. Browse to /admin/reports/upgrade-status in your D8 site

  • 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 8.x-5.25 and the “drupal.org” version is 6.0.2, change the webform line in composer.json to: drupal/webform”: “^6.0”
    • 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: ^8 || ^9 to designate that the module is compatible with Drupal 9. 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 “^8 || ^9”.

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_9.php ./web/modules/custom
php update_module_core_version_to_9.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 listed under “fix with rector”, that’s just what we’re doing to do.

  • First, install rector with the following command:
composer require --dev palantirnet/drupal-rector
  • For each module in the “Fix with Rector” list, run rector. This will automatically fix a significant number of compatibility issues:x
vendor/bin/rector process web/modules/custom/MODULE-NAME-HERE

9. 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

10. Follow the final upgrade steps here: https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-to-drupal-9-or-later

11. 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.