Drupal Techniques: How to upgrade Drupal

Written on September 29, 2021

Category: Drupal Techniques

Author: David Rodríguez, @davidjguru

Picture from Unsplash, by @saddy143
Picture from Unsplash, user Raul Varzar, @calypso999

As you may have heard, the End Of Life for Drupal 8 is near. This is closing fast, very fast now. In fact the date for Drupal 8 EOL is November 2nd 2021, aligning this transition with the same EOL for one of the most important dependencies and key components: Symfony 3. Yep, the last minor version available for Symfony 3 (3.4) has marked like end for bug fixes and security fixes november 2021. As a rule, supported versions of Drupal must use supported version of Symfony, so this is the end unless you perform and upgrade in your Drupal platform…

A few days ago I had to work on a upgrade to Drupal 9 and along the way, I’ve taken some useful notes about the process. After publishing a quick guide for internal consumption I’ve decided to write a more extended version with all the issues. Since enough articles with FUD have already been published about the necessary Drupal upgrade, I won’t dwell on the risks or in potential problems: There are less than eight weeks left until Drupal 8 community support development stops and there is little time if you want to focus on Drupal 9 upgrades with your team. Read this article, review its steps, make your own checklist and get started!


This post was composed from my current position as Senior Drupal Developer at Digitalist Sweden, one of the biggest companies oriented to Open Source in Europe and specifically focused in Drupal.

Drupal 7, 8 and 9 timeline about lifecycle
Image taken from drupal.org/how-to-prepare-for-drupal-9

In addition, there are a couple of premises or prerequisites that we must satisfy, just like a pair or assumptions:

Assumption 1: We’re working in a Drupal 8 installation now or in a Drupal major version > 7 (Drupal 9 to Drupal 10 maybe). This is not an article about Drupal Migrations, so I’m not covering a Drupal 7 to Drupal 9 migration and upgrading (a more extensive, complex and exhaustive process due to the huge structural difference in the jump between Drupal 7 and Drupal 8), so this post is for Drupal > 7 installations, sorry.

Assumption 2: Your Drupal installation is under the control of Composer as dependency manager. I’m quite aware that there are still projects that don’t use Composer as a main dependency manager and also -as in Allen Ginsberg’s poem: Howl poem- “I saw the best minds of my generation destroyed by madness”. But you need composerizate your project (that is, put it under Composer management). This article is for Drupal 8 installations using Composer.

TL;DR -> This is a post about how to execute (steps, tips, risks…) the upgrading process from major versions of Drupal (D8 to D9, D9 to D10, etc.).

  • If you want to learn how to execute Drupal upgrading reading resources from external sources, I have a Gist in Github with my favourite content, here.
  • If you came here looking for information about Drupal updates for minor versions (Drupal 9.2.6 -> 9.2.7 -> 9.2.8), better visit this snippet I have in Gitlab with related information.
  • If you want to have a quick overview, download the image below and zoom in to see the recommended steps.

See the image below:
How to upgrade between major verions of Drupal

Table of Contents.

1- Setting the scenario
2- Sorting the toolbox
3- Assesing the status of your project
4- Preparing the work
5- Executing the work
6- Troubleshooting
7- Read More
8- :wq!

1- Setting the scenario

As a first step we need to select our Drupal installation on which we have to perform the upgrade.

GOAL: Have an enabled Drupal setup.

I’m going to deploy in my local environment a new Drupal 8 site for testing updates to Drupal 9. I will call it “drupal8function”, with an user “admin” and password “admin”, using DDEV as deployment tool, as I wrote down here in this gitlab snippet, just by typing the next commands in prompt:

$ mkdir drupal8function && cd drupal8function
$ ddev config --project-type=drupal8 --docroot=web --create-docroot
$ yes | ddev composer create "drupal/recommended-project:^8"
$ ddev composer require drush/drush drupal/admin_toolbar drupal/devel
$ ddev exec drush si --site-name=drupal8function --account-name=admin --account-pass=admin -y
$ ddev drush en -y admin_toolbar devel
$ ddev drush cr
$ ddev start && ddev launch

I need some custom resources for testing so I’ll clone some Drupal 8 modules that I have in my Gitlab repository. My idea is taking some modules in a Drupal 8 version and then moving to my /custom folder enabling it by drush, so I’ll have Drupal 8 custom resources ready to review for the upgrade to Drupal 9. Let’s see some D8 modules:

$ git clone https://gitlab.com/davidjguru/drupal-custom-modules-examples.git
$ mkdir ./web/modules/custom
$ mv drupal-custom-modules-examples/links_example ./web/modules/custom/
$ mv drupal-custom-modules-examples/headers_manager/ ./web/modules/custom/
$ mv drupal-custom-modules-examples/Migrations/migration_basic_module/ ./web/modules/custom/
$ ddev drush en -y links_example headers_manager migration_basic_module
$ ddev drush

Also, I’ve added some patches for Drupal 8 core modules, by adding some links in composer.json files:

"patches": {
  "drupal/core": {
    "Content_entity, config_entity Plugins": "https://www.drupal.org/files/issues/2020-09-24/3172853-2.patch",
    "AccessAwareRouter HTTP method.": "https://www.drupal.org/files/issues/2018-12-12/2706241-34.patch",
    "Sets langcode.": "https://www.drupal.org/files/issues/2020-06-10/locale-config-langcodes.patch",
    "Layout builder assign inline block access.": "https://www.drupal.org/files/issues/2021-03-22/3047022-71.patch",
    "Generate pathauto aliases.": "https://www.drupal.org/files/issues/2020-11-06/3181070-possible-need-to-change-the-way-menulinkmanager-updates-menu-item-and-menu-tree.patch"

Ok, now I have a semi-real scenario composed by a Drupal 8 core, patches, some contrib modules and custom resources in Drupal 8 too. So when I ask for the Drupal core version to Composer, I’m getting:

How to upgrade to Drupal 9 one

The next step will be Preparing the toolbox.

2- Sorting the toolbox

First of all I think we need to prepare a toolbox with some basic utilities for our upgrading plan.

GOAL: Have a set of well-know and tested tools.

I have selected here only five basic resources, very easy to use. These are the following items:

2.1- upgrade_status

Before studying and designing the process for update your Drupal installation, maybe you need a high-level view, a fast summary about what is the current status in your platform. The contrib module “Upgrade Status” can provide you a fast review about this and it provides you with some solutions and tips too.

$ ddev composer require drupal/upgrade_status
$ ddev drush en -y upgrade_status
$ ddev drush cr

(Avoid using the command ddev if you are not using DDEV, of course. Or change by lando command.)

And if you don’t want touch your Drupal core, ask for dev versions for core and dependencies getting first your current core version in terminal:

$ ddev composer show drupal/core | grep versions
versions : * 8.9.18

$ ddev composer require --dev drupal/core-dev:8.9.18 --update-with-all-dependencies
$ ddev composer require drupal/upgrade_status
$ ddev drush -y upgrade_status
$ ddev drush cr

Once installed and enabled, this module will offer you a GUI and a pair of new drush subcommands in order to get the reports. We’ll see the results in a next section.

2.2- php-stan

PHPStan is a PHP Static Analysis Tool created by Ondřej Mirtes and others that combined with a set of custom rules for Drupal can do the job reviewing the status of your code. First, We have to install all the resources:

$ ddev composer require  --dev phpstan/phpstan \
  phpstan/extension-installer \
  mglaman/phpstan-drupal \

The phpstan/extension.-installer will autoconfigure PHPStan to load phpstan-drupal and the deprecation-rules, the resource that will delivery the reports about using deprecated code in your installation and resources.

Then we can run phpstan against the selected resources by doing something like:

$ ddev php vendor/bin/phpstan.phar analyze web/modules/custom/my_custom_module

And you can change the level for the review, from 0 (the loosest) to 8 (the strictest), passing the parameter -l to the command:

$ ddev php vendor/bin/phpstan -l 4 analyze web/modules/custom/my_custom_module

2.3- drupal-check

Drupal Check is a static analysis tool developed by Matt Glaman based in PHPStan, a very useful resource for these updating processes, allowing us to search for deprecated code in our resources, errors and some more interesting information. You can use it as a new Composer dependency or as VSCode extension.

We’re going to install the tool through Composer, by doing:

$ ddev composer require mglaman/drupal-check --dev

And we’ll have available a new command from prompt: ‘drupal-check’. We’ll cover the use in a next section.

2.4- drupal-rector

Drupal Rector is a fixing deprecated code tool for Drupal, built by Palantir and available as a Composer dependency. It can inspect, proposing and apply patches for changes in your software from its code reviews.

2.5- backward_compatibility

This is a little contrib module oriented to simple cases: there are a lot of contrib modules in Drupal that only requires add a single line in its module.info.yml file, I mean:

core_version_requirement: ^8 || ^9

Well, instead of patching every contrib module with this problem, just install the resource and it will work’round the Issue. Just by doing:

$ composer require drupal/backward_compatibility
$ drush en -y backward_compatibility
$ drush cr

And nothing more! (simple solutions for very specific use cases).

3- Assesing the status of your project

Now It’s time to get a reliable image of the status of our project through the tools selected in the former section.

GOAL: Have a true picture of the work to be done.

It will be no secret to say that our field of work in this updating process will be mainly in the custom zone of our resources: We will dedicate a large percentage of time to the adaptaion of our custom modules, our custom themes and our patches applied to the project that are in local folders and not in Drupal.org (which is another category of custom work for us).

3.1- Taking a snapshot of your platform

Before we can estimate how much time we will spend and how many actions we need to implement, let’s do some initial data collection and prepare some resources. This will give us a useful snapshot of the status of our platform.

Ok, first you have to review the current status of your local deploy. Remember that your installation has five pillars, five main columns:

  1. Composer files: composer.json and composer.lock
  2. Config Files, usually in /config/sync/
  3. The files folder, usually in /web/sites/default/files/
  4. The database of your Drupal installation
  5. All your custom work: custom modules, custom themes and (maybe) custom patches.

Put all the above resources in a safe place of your choice.

Remember that if you did your homework and assignments right, then the alignment between “Active Configuration” (database) and “Passive Configuration” (configuration files) will be complete, I mean:

$ ddev drush cex
[notice] The active configuration is identical to the configuration in the export directory (sites/default/files/sync).

$ ddev drush cim
[notice] There are no changes to import.

And there will be no change to identify. Otherwise, you should always prioritize the active database configuration as an up-to-date reference of the state of your Drupal installation.

Some Steps:

  1. Preparing your containers and backups
  2. Check your current version for Drupal Core
  3. Enable the upgrade_status module and check results
  4. Check code with drupal-checker and drupal-rector

3.2- Containers and Backups

It’s time to review some special configurations and values in your environments…what versions of Nginx, Apache, MySQL, Postgres or MariaDB you have? check the current versions in your environments, containers, etc.

3.3- Current version for Drupal Core

Let’s confirm our core version by typing in prompt:

$ ddev composer show drupal/core | grep versions
versions : * 8.9.18

3.4- Upgrade Status

After enabling the upgrade_status module, we’ll inspect the current status of our installation accesing to /admin/reports/upgrade-status and seeing the first information area of the status report:

Upgrade Status fist region

Here you can see the general review of your resources, custom and contrib, and seeing the changes to do, you will be able to estimate the amount of time you will need to dedicate to these updates,, about the hosting, core and environment:

Requirements in core and hosting

Or by seeing the specific modules:

Changes required in modules

We can use the new Drush commands provided by the module to explore some specific modules, doing:

 $ ddev drush upgrade_status:analyze admin_toolbar
 [notice] Processing /var/www/html/web/modules/contrib/admin_toolbar.

Admin Toolbar,  3.0.2
Scanned on Mon, 09/20/2021 - 17:15


STATUS         LINE                           MESSAGE                           
Check manually 15   Class PHPUnit\Framework\TestCase not found.                 



This module is ready for Drupal 9.

3.5- Drupal-Checker and Drupal-Rector

$ drupal-check -a web/modules/contrib/admin_toolbar

Install by doing:

$ ddev composer require --dev palantirnet/drupal-rector

You can give to Drupal Rector a GUI from your Drupal installation:

$ ddev composer require 'drupal/upgrade_rector:^1.0@alpha'
$ ddev drush en -y upgrade_rector
$ ddev drush cr

And then go to /admin/reports/upgrade-rector and see the reviews available for contrib and custom resources:

3.6- Get a list of deprecated resources

You can check the current status of all your dependencies, getting a report with related information from Composer. Just run:

$ ddev composer outdated

And you will get:

alchemy/zippy                            0.4.9    1.0.0   Zippy, the archive manager companion
asm89/stack-cors                         1.3.0    v2.1.1  Cross-origin resource sharing library and stack middleware
chi-teck/drupal-code-generator           1.33.1   2.5.1   Drupal code generator
composer/composer                        2.2.6    2.2.9   Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.
composer/installers                      v1.12.0  v2.1.0  A multi-framework Composer library installer
composer/pcre                            1.0.1    3.0.0   PCRE wrapping library that offers type-safe preg_* replacements.
composer/semver                          3.2.6    3.3.1   Semver library that offers utilities, version constraint parsing and validation.
composer/xdebug-handler                  2.0.4    3.0.3   Restarts a process without Xdebug.
consolidation/annotated-command          4.3.2    4.5.2   Initialize Symfony Console commands from annotated command class methods.
consolidation/config                     1.2.1    2.1.0   Pr


Now you have a little overview about all the pending tasks for upgrading all in your Drupal installation.

4- Preparing the work

Somebody, somewhere - maybe yourself - needs to know what needs to be done, risks we run and how much time / effort the upgrade needs.

GOAL: Haver a reliable estimation of the process.

Ok, after putting in a safe place a copy of the five basic parts of your installation (config, database dump, files folder, composer files and all your custom works -themes, modules, patches, etc. and after checking the state for update, you’ll be able to build a map with all the required tasks related with the update, I mean:

  • List of resources that only requires basic and fast changes: the quickest and easiest bet to execute. Small and perhaps repetitive changes that you might be able to run the same way in the same bash script or through the same Git patch.

  • List of resources that contains deprecated code: If you have ignored successive warnings and code deprecation warnings since previous versions (don’t be like me), you may need time to make adjustments to this part. Check the warnings thoroughly now.

  • List of resources that requires refactoring or advanced changes: Perhaps one of the most complex parts. You may take time to balance this part according to the latest changes in core and contributed modules, to adapt your own functionality in custom modules and to rewrite code. Be cautious and value well this estimation.

  • List of items to update in environments (versions for PHP, MariaDB and other containers stuff): A part that tends to be overlooked but someone will take care of executing… Do our current Docker images work? are our containers up to date? do they require a higher version of a resource? don’t forget this section.

After reviewing all this and compiling all the information provided by the tools discussed above as output, you can now think about what’s left, what output can we expect, you can combine all your estimates and build a tracking document of all the tasks associated with the upgrade. I use something like this, something primary but very useful as a checklist:

Filling a worksheet for the Drupal 9 upgrading

5- Executing the upgrade

The time has come to make the necessary changes and adjustments. Let’s go!

GOAL: Have an experienced process (trial, error, trial, error…)

5.1- Remove some resources

Remove drupal/console: (usually causes problems with symfony dependencies), so If you have installed drupal console, remove it as first step.

$ ddev composer remove drupal/console

Now, remove drupal/core and/or drupal/core-recommended from composer.json. Look for drupal/core-recommended or drupal/core in composer.json and remove the line(s):

"drupal/core-recommended": "^8.9.0"

If you have drush and devel, which are widely used, also manually edit the versions:

"drupal/devel": "^4.0",
"drush/drush": "^10.0.0",

Then run composer update again:

$ ddev composer update

This will remove drupal core from your installation but will update the contrib resources.

5.2- Set your new Drupal Core version

Add drupal/core-recommended:9.0.0 to composer.json

"drupal/core-recommended": "9.0.0",

Now run composer update one more time:

$ ddev composer update

5.3- Delete modules with problems

In my case, During the last tasks of upgrading projects to Drupal 9, I have some problems with a specific contrib module: multivalue_form_element

Problem 1
- Conclusion: remove drupal/core-recommended 9.0.0
- Conclusion: don't install drupal/core-recommended 9.0.0
- Conclusion: don't install drupal/multivalue_form_element 1.0.0-beta2|don't install

Why? Well the module seems to be available only from Drupal 9.1:

Multivalue Form Element Module Page

When deleting this module from composer.json, run composer update and now You will have the new core version (9.0.0) installed. We will back to this module in next steps.

5.4- Upgrade to latest Drupal 9 version

After this, change your drupal/core-recommended line in composer.json to:

"drupal/core-recommended": "^9.0.0",

And re-run composer update .

5.5- Update patches

Sure you have some patches applied to your Drupal Core from the composer.json file. I have, for example these, mixin’ contrib from drupal.org and custom from a local folder within the project:

"drupal/core": {
"Add content_entity and config_entity DataType plugins (https://www.drupal.org/project/drupal/issues/3172853)": "https://www.drupal.org/files/issues/2020-09-24/3172853-2.patch",
"AccessAwareRouter does not respect HTTP method (https://www.drupal.org/project/drupal/issues/2706241)": "https://www.drupal.org/files/issues/2018-12-12/2706241-34.patch",
"Claro removes contextual links for inline blocks translate - only needed when using claro in layout builder": "./patches/claro-preprocess-contextual.patch",
"Sets the langcode for config export to en": "https://www.drupal.org/files/issues/2020-06-10/locale-config-langcodes.patch",
"Layout builder fails to assign inline block access dependencies for the overrides section storage on entities with pending revisions.": "https://www.drupal.org/files/issues/2020-09-10/3047022-43.patch",
"Generate pathauto aliases when rearranging menu.": "https://www.drupal.org/files/issues/2020-11-06/3181070-possible-need-to-change-the-way-menulinkmanager-updates-menu-item-and-menu-tree.patch",
"Remove entity constraint validator for inline blocks": "./patches/3053881-30-reroll-8.x.patch",
"Replace token module internal link to nodes with a entity link": "./patches/menu_ui-token-uuid-to-id.patch",
"Drupal dialog respect drupalAutoButtons: false": "./patches/drupal-dialog-respect-drupalautobuttons.patch",
"Make drupalAutoButtons a boolean": "./patches/OpenDialogCommand-drupalAutoButtons-boolean.patch",
"Tabledrag nested stuff.": "https://www.drupal.org/files/issues/2020-12-08/3092181-142-8X_0.patch",
"Error in computed image fields (width, height) when saving nodes": "https://www.drupal.org/files/issues/2019-02-11/ignore_width_height_on_untranslatable_field_comparision_2941092_8.patch",
"Vary block definitions on language": "./patches/block-manager-cache-key.patch",
"Expose resetSize from dialog position to the Drupal object": "./patches/expose-reset-size-to-drupal-object.patch"

So when I’m trying update my Drupal core I’m getting these errors:

Could not apply patch! 
  Skipping. The error was: Cannot apply patch 
Could not apply patch! 
  Skipping. The error was: Cannot apply patch ./patches/drupal-dialog-respect-drupalautobuttons.patch
Could not apply patch! 
  Skipping. The error was: Cannot apply patch 

As you can see, I’m having problems with three patches for Drupal Core. Ok, so here we have to do some manual work…We have to check for every patch:

  1. If the patch was already applied to the 9.x development branch, so It’s not necesary to apply now in the upgrade.
  2. If the patch was not applied, then you have to look for a new re-rolled patch ready for the new version of Drupal (> 9.x.x.).
  3. If the patch doesn’t come from drupal.org and it’s a custom solution located in /patches directory, then you’ll have to work in the migration of the resource, re-rolling the patch. :-/
  4. If the patch has not been applied and there is no version for Drupal 9 either, so you have to talk with your team, including your scrum master and / or Product Owner. The original problem will come back to the Drupal installation until you or somebody in the Drupal community can port the patch to Drupal 9. Sorry :-/

And looking the original Issues, I can see versions for Drupal 9.2, as here.

I found a solution for Drupal 9 here.

Or there:
Seems to be resolved from Drupal 9.2.

My third patch with problems is a local custom patch in /patches folder, so I have to do some coding review here :-/

5.6- Reinstall modules with Issues

After install the updated core, upgrading to the latest version available and working with patches, now can request the problematic modules, like the multivalue_form_element:

$ ddev composer require drupal/multivalue_form_element

Remember that you can avoid problems pre-testing the installation of dependencies in Composer by using:

$ ddev composer install --dry-run

5.7- Run updates in database

Important: Not run the database updates before install the modules with issues: You can have the module saved as active in database but the codebase doesn’t exist, due to this you’ll get a lot of problems. Remember: first update core, then install modules with issues and after all, launch the database updates.

$ ddev drush updb -y
$ ddev drush cr

5.8- Review all your custom work

You can use the well-formed tools commented in the section about tooling, doing so:

$ ddev composer require mglaman/drupal-check --dev
$ ddev drupal-check -a web/modules/custom

5.9- Checking new installed versions

name     : drupal/smtp
descrip. : Allow for site emails to be sent through an SMTP server of your choice.
keywords : 
versions : * 1.0.0
type     : drupal-module
license  : GNU General Public License v2.0 or later (GPL-2.0-or-later) (OSI approved) https://spdx.org/licenses/GPL-2.0-or-later.html#licenseText
homepage : https://www.drupal.org/project/smtp
source   : [git] https://git.drupalcode.org/project/smtp.git 8.x-1.0
dist     : [zip] https://ftp.drupal.org/files/projects/smtp-8.x-1.0.zip 8.x-1.0
path     : /app/backend/web/modules/contrib/smtp
names    : drupal/smtp

source : https://git.drupalcode.org/project/smtp
issues : https://www.drupal.org/project/issues/smtp

drupal/core ^8.8 || ^9**
phpmailer/phpmailer ^6.1.7


$ ddev composer show drupal/pathauto


name     : drupal/pathauto
descrip. : Provides a mechanism for modules to automatically generate aliases for the content they manage.
keywords : 
versions : * 1.8.0
type     : drupal-module
license  : GNU General Public License v2.0 or later (GPL-2.0-or-later) (OSI approved) https://spdx.org/licenses/GPL-2.0-or-later.html#licenseText
homepage : https://www.drupal.org/project/pathauto
source   : [git] https://git.drupalcode.org/project/pathauto.git 8.x-1.8
dist     : [zip] https://ftp.drupal.org/files/projects/pathauto-8.x-1.8.zip 8.x-1.8
path     : /app/backend/web/modules/contrib/pathauto
names    : drupal/pathauto

source : https://cgit.drupalcode.org/pathauto
issues : https://www.drupal.org/project/issues/pathauto
documentation : https://www.drupal.org/docs/8/modules/pathauto

drupal/core ^8.8 || ^9**
drupal/ctools *
drupal/token *


$ ddev composer show drupal/core

name     : drupal/core
descrip. : Drupal is an open source content management platform powering millions of websites and applications.
keywords : 
**versions : * 9.2.5**
type     : drupal-core
license  : GNU General Public License v2.0 or later (GPL-2.0-or-later) (OSI approved)

5.10- Remove tooling for upgrade

Remove the upgrade_status contrib module or the extra resources by typing:

$ ddev drush pmu -y upgrade_status
$ ddev composer remove drupal/upgrade_status
$ ddev drush cr

$ ddev composer remove mglaman/drupal-check --dev

5.11- Commit files with changes

You will have to commit to repository the new versions of your composer.json and composer.lock files, in order to get the new versions in the next deploys for environments.

6- Troubleshooting

Maybe it’s not your last update or a colleague needs help: make your experience a validated learning experience.

GOAL: Have a reusable set of problems and solutions.

Here I would like to gather some problems and limitations observed in various Drupal 9 upgrade tasks.

6.1- GraphQL is giving me some errors

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires drupal/graphql ^4.1 -> satisfiable by drupal/graphql[4.1.0].
    - drupal/graphql 4.1.0 requires drupal/typed_data * -> found drupal/typed_data[dev-1.x, 1.0.0-alpha1, ..., 1.x-dev (alias of dev-1.x)] but it does not match your minimum-stability.

And so, by doing: ddev composer require drupal/typed_data

$ ddev composer require drupal/typed_data                                                                                                                                        
Could not find a version of package drupal/typed_data matching your minimum-stability (stable). Require it with an explicit version constraint allowing its desired stability.

It can be changed in composer.json file, where you’ve marked stability as “stable”, so composer won’t accept the dependency in alpha, so you can change your requirements, allowing the minimum-stability of packages in dev or alpha but prefer stable.

This has to be changed in composer.jsonfile in your project root folder:

 "conflict": {
        "drupal/drupal": "*"
    "minimum-stability": "dev",  <= THIS
    "prefer-stable": true,**
    "config": {
        "sort-packages": true,
        "platform": {
            "php": "7.4"

But it’s not a good idea, cause you can change the level of minimum-stability and it could be a risk for your project. Instead, use the recommended way that is only install in alpha the dependency, step by step by doing:

$ composer require drupal/typed_data:@alpha
$ composer require drupal/graphql

6.2- I can’t create new users

I noticed that after an update to Drupal 9, in some projects is not possible create a new user in path /admin/people/create, you can’t see the second password field “Confirm Password” and due to this, the form is not saving a new user.

Is this happening to you? Don’t worry, it has an easy solution. Let’s see.

  • First, this happens when using custom themes based in Claro (https://www.drupal.org/project/claro) now, in Drupal Core -but experimental by now-.

  • Second, The error is coming from a change in Claro theme. In Claro 9.2.5 (Drupal Core 9.2.5) there is a change in a library declaration and this was moving from one to another block.

  • Third, you only need edit your custom_theme.info.yml file and move the user/drupal.user: claro/form.password-confirm pair from the block “libraries-override” to the block “libraries-extend”. Now:

libraries-extend: <= HERE
    - claro/ajax
    - claro/form.password-confirm  <= HERE
    - claro/views
  • Fourth, only save the change and clear cache by doing $ drush cr and now you’ll see the second field, saving new users.

  • Fifth (remember), Claro theme is experimental in Drupal Core, and is not stable.

  • Sixth (more remember), You must to know that subtheming from Admin Themes are not offically supported in Drupal, so be carefull: Related Issue in Drupal.org.

Read more about this Issue in Drupal.org.

Read more about subtheming an Admin theme in Drupal.org: drupal.org/issues/3118850.

6.3- Config Split not seem to work well in deploys

After updates to Drupal 9 and moving forward versions of contributed modules, in some cases there are problems when importing configuration files orchestrated by the contrib module config split and launched from some task runners tools like dropcat, robo, drobo (robo for Drupal) etc.

Well, some Drush commands aliases has been changed in Config Split and maybe you have to change your commands:

But the most important thing is:… the version 2.x is not recommended by the module maintainers…so please, downgrade to the former version.

Config Split recommended version

6.4- Review (and change) deprecated code

As part of the code upgrades - especially working with custom code - in the move to Drupal 9 you will have to make mandatory changes that were previously only optional: deprecated code that (now yes) you will no longer be able to use in D9 (in D8 you were only informed or warned).

For example, I have received warnings but I have not changed some services (don’t be like me) and when I got to Drupal 9 I received errors like this:

**You have requested a non-existent service "entity.query".** 
Did you mean one of these: "entity.query.config", "entity.query.sql", 
"pgsql.entity.query.sql", "entity.query.null", "entity.query.keyvalue"? 
in Drupal\Component\DependencyInjection\Container->get() 
(line 156 of 

This message is about the Issue: drupal.org/2849874 talking about a service deprecation. It has been around for a long time but now generates errors and should be removed.

In this case I was using the service:

$query = Drupal::service('entity.query')->get('menu_link_content');
$query->condition('link.uri', 'entity:node/' . $node->id());
$result = $query->execute();

It’s just a service provided by the class QueryFactory: api.drupal.org/entity.query

So now you have to use the general manager for entities, the entityTypeManager service:

$query = \Drupal::entityTypeManager()->getStorage('menu_link_content')->getQuery();
$query->condition('link.uri', 'entity:node/' . $node->id());
$result = $query->execute();

And entityQuery is available too:

$query = \Drupal::entityQuery('menu_link_content');
$query->condition('link.uri', 'entity:node/' . $node->id());
$result = $query->execute();

Please, think about using review-code tooling like drupal-check and drupal-rector in order to avoid these kind of errors in code deprecations.

7- Read More

Many others have also written about the upgrade process. There is also information from Drupal.org, as well as many related experiences. If you want to go deeper into this, I recommend here several reading materials from different organisations, companies and authors.

8- :wq!

Written on September 29, 2021