Drupal ^8.8 || ^9 - Upgrade from 8.9.19 to 9.2.6 | Tutorial

Drupal 8 to Drupal 9 upgrade abstract image

The Topic: Upgrading Drupal 8.9.19 to 9.2.6. A record of my process.

I have attempted to upgrade from Drupal 8 to 9 for some time now. At times, I found the process confusing, almost contradictory. Then again, I did not allocate focussed time to get the job done. Over the past few days I knuckled down, dissected the documents and tutorials I found and succeeded.

This article is a chronicle of my process. I am not saying it is absolutely correct, nor the most efficient. I am sure there are more elegant ways of doing this. Furthermore, I think it is possible that each site's update process will be slightly different. This is due to Composer being key to the process. Composer 1 is deprecated, and Drupal 9 needs Composer 2. I was still using Composer 1 and first needed to update to 2.

The contributed and custom modules the site uses, theme, underlying Symfony Framework and the Composer plugins used all impact the upgrade process. Drupal 8 sites could have a myriad of combinations of these components.

The Process

Below are the steps I took.

  1. Back up database and code. As an additional precaution, I took a snapshot of my server.
  2. Update Core and all modules to the latest version.
  3. Check if the modules you are using are compatible with Drupal 9. Uninstall the modules that are not.
  4. Make a list of the modules that have D9 versions not compatible with Drupal 8, however are required and or desired for Drupal 9.
  5. If you have custom modules or themes, ensure they are Drupal 9 compatible.
  6. Set appropriate file and directory permissions.
  7. If you are using Composer 1, upgrade this to Composer 2.
  8. Upgrade Drupal, contributed modules and any Symphony requirements not triggered by the update process.
  9. Update database.
  10. Check for missing elements in composer.json file.

Let's look at a real-world example.

3 - Check Module Compatibility

Steps 1 and 2 should be self-explanatory. To check if the module is compatible with Drupal 9. I will use Twig Tweak and Module Filter as examples.

  • I have updated Twig Tweak to 8-x-2.9. Go to the official module page, and we can see:
                8.x-2.9 released 16 December 2020
                Requires Drupal: ^8 || ^9
    This module is Drupal 9 compatible.
  • I have Module Filter 8.x-3.2 installed. On the official page we can see:
            8.x-3.2 released 5 March 2021
            ✓ Recommended by the project’s maintainer.
    This module is not Drupal 9 ready. The module is not essential to the site, so we can uninstall it and remove it from our project composer.json file.
    drush pm:uninstall module_filter
    composer remove drupal/module_filter

Do this process for all the modules installed.

A note on the Devel module. I had 8.x-2.1 installed. This is not Drupal 9 compatible, however 4.1.1 is. I use Devel Kint, included in the 8.x-2.1 version, but not included in the 4.1.1 version. I elected to uninstall the module (and Devel Kint) rather than upgrade to 4.1.1. I installed 4.1.1 after the Drupal 9 upgrade was complete.

Check for Non-compatible Drupal 8 Modules needed for Drupal 9

Some contributed modules have Drupal 9 versions that are not compatible with Drupal 8. We may want these Drupal 9 versions installed. In some cases they are required to be upgraded in order to continue working. While it was not installed on my site, Permissions by Term is such a module.

Looking at our Twig Tweak module page, or on our Available Updates page for that matter. We can see that Twig Tweak has a 3.1.2 version. This is Drupal 9 compatible but not Drupal 8.

Twig Tweak not Drupal 9 version not compatible with Drupal 8

Editor Advanced Link is another such module.

We will upgrade these modules during the Drupal 9 upgrade process.

Ensure any Custom Modules or Themes are Drupal 8 and 9 Compatible

I had both a custom module and custom theme installed. The theme is a sub-theme of Classy utilizing the Bootstrap 4 framework.

All I needed to do in my my_theme.info.yml and my_module.info.yml files was change core: 8.x to core_version_requirement: ^8 || ^9

Upgrade from Composer 1 to Composer 2

Before upgrading we need to do a couple of checks. As I mentioned, your site may have different requirements. Perhaps read this page first. It is the page I used for my process below.

My Process:

  1. While on Composer 1, upgrade plugins / local packages if required
  2. While on Composer 1, remove plugins / local packages no longer required
  3. Upgrade to Composer 2

Upgrade Plugins / Local Packages

Upgrade composer/installers:

  • composer require composer/installers:^1.9 --no-update - this updates composer.json file.
  • composer update composer/installers --with-all-dependencies --dry-run - this will show if there are errors. If none, proceed to next step
  • composer update composer/installers --with-all-dependencies

Upgrade cweagans/composer-patches:

  • composer require cweagans/composer-patches:^1.7 --no-update - this updates composer.json file.
  • composer update cweagans/composer-patches --with-all-dependencies --dry-run - this will show if there are errors. If none, proceed to next step
  • composer update cweagans/composer-patches --with-all-dependencies

In this regard, these are the only plugins / local packages that I needed to upgrade. I could now upgrade to Composer 2. composer selfupdate --2

Remove Plugins / Local Packages

In my case, the only plugin that needed attention was drupal-composer/drupal-scaffold. Drupal 9 uses drupal/core-composer-scaffold, which we require on the upgrade process below.

composer remove drupal-composer/drupal-scaffold --no-update

I was now in a position to upgrade Drupal.

The Drupal Upgrade Process

I used a Drupal Document Page for my Composer update commands.

    composer require 'drupal/core-recommended:^9.2.0' 'drupal/core-composer-scaffold:^9.2.0'
    'drupal/core-project-message:^9.2.0' --update-with-dependencies --no-update

With my process there were slight variations I wanted:

  • I wanted to upgrade Twig Tweak and Editor Advanced Link as well.
  • Based on a video, Upgrade From Drupal 8 to 9 with composer I had watched, I anticipated errors. These errors would show me what additional elements needed to be upgraded. Despite using --with-all-dependencies, these upgrades were not being triggered by the upgrade process. They will need to be explicitly triggered.

My initial command was:

    composer require drupal/core-recommended:^9.2.0 drupal/core-composer-scaffold:^9.2.0
    drupal/core-project-message:^9.2.0 drupal/editor_advanced_link:^2.0 drupal/twig_tweak:^3.1

This outputted the following errors:

    drupal-composer/drupal-project  dev-afc_dev  requires          drupal/core (^8.7.0)
    drupal/core                     9.2.6        requires          symfony/console (^4.4)
    drupal-composer/drupal-project  dev-afc_dev  does not require  symfony/console (but v3.4.47 is installed)
    drupal/core                     9.2.6        requires          symfony/dependency-injection (^4.4)
    drupal-composer/drupal-project  dev-afc_dev  does not require  symfony/dependency-injection (but v3.4.47 is installed)

This had me very confused. Because my composer.json had "drupal/core": "^8.7.0", as required, it was attempting to honor this. In no documentation have I read that this needs to be removed from the composer.json file. Anyway, I did remove it. composer remove drupal/core --no-update. I then ran the above Drupal 9 upgrade command again. I had better luck. The following 'meaningful' errors were shown.

    Problem 1
    - drush/drush is locked to version 9.7.3 and an update of this package was not requested.
    - drupal/core-recommended 9.2.0-beta1 requires symfony/yaml v4.4.22 -> satisfiable by symfony/yaml[v4.4.22].
    - ........

This showed me that Drush needed to be upgraded from 9 to 10. Also symfony/yaml is required. My command changed to:

    composer require drupal/core-recommended:^9.2.0 drupal/core-composer-scaffold:^9.2.0
    drupal/core-project-message:^9.2.0 drupal/editor_advanced_link:^2.0 drupal/twig_tweak:^3.1
    drush/drush:^10.0.0 symfony/yaml:^4.4.0 --update-with-all-dependencies

The Drupal 9 codebase was installed successfully. Running drush updb initiated successful required database updates.

Check for Missing Elements in composer.json

Running git status revealed untracked files that confused me at first.


I assumed this was coming from core-composer-scaffold. I checked the composer.json file from a clean Drupal 9 install. I found the following:

    "drupal-scaffold": {
        "locations": {
        "web-root": "web/"

"Locations" was missing from my file. I added it, removed the untracked directories and ran composer update. All seemed fine.

My site had been updated to Drupal 9. :-)

Hire Me? Lets talk!

I am available for remote freelance work to select clients. Please contact me

Related Articles


This tutorial was written with the help of the following excellent contributions.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.