Skip to main content
Table of contents

 

Updating to Drupal 10

Begin by upgrading Drupal 9 to the latest version.  Currently that is 9.5.10

 

Review existing modules and themes

Using the Upgrade Status (https://www.drupal.org/project/upgrade_status) module, review the state of existing installed and uninstalled modules and themes.  This includes removing deprecated modules in Drupal 10 such as Color, HAL, RDF and themes Bartik and Stable.  Note, for Drupal 10, the theme Stable is now Stable9.

Note - while these deprecated modules are no longer part of Drupal core.... access to some of them are available

Module Version URL Drupal version
Color 1.0.3 https://www.drupal.org/project/color ^9.4
HAL 2.0 https://www.drupal.org/project/hal ^10
RDF ^2.1 https://www.drupal.org/project/rdf ^9.4 || ^10.0

Obviously, as you work through the upgrade process, and your current Drupal version is 9.5, upgrading a module with a Drupal base version of ^10 cannot be installed until the upgrade process has been completed.

 

 

Upgrade steps

Preparation to upgrade

Now that you have prepared your site, your first step in the upgrade process is to temporarily add write access to protected files and directories:

chmod -R 777 {path}/web/sites/default
chmod 666 {path}/web/sites/default/*settings.php
chmod 666 {path}/web/sites/default/*services.yml

Prepare core-recommend and dev-dependencies changed in the composer.json file.  The file will be updated similar to

    "require": {
        /.../
        "drupal/core-composer-scaffold": "^9.5",
        "drupal/core-project-message": "^9.5",
        "drupal/core-recommended": "^9.5",

Run the following

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

Change

    "require": {
        /.../
        "drupal/core-composer-scaffold": "^10",
        "drupal/core-project-message": "^10",
        "drupal/core-recommended": "^10",

Also updating

    "require-dev": {
        "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
        "drupal/core-dev": "^9.5",
        /.../

Check if you have Core dev script?  If so, then run

composer require 'drupal/core-dev:^10' --dev --update-with-dependencies --no-update

Response

    "require-dev": {
        "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
        "drupal/core-dev": "^10",
        /.../

 

Drush version

Check the current version of Drush being used, as Drupal 10 is best to run off Drush 12

drush --version

Response

Drush Commandline Tool 11.6.0

Prepare the update to version by

composer require 'drush/drush:^12' --no-update

 

Time to perform the update

With the preparation completed, let's run the update

composer update

 

Update the database

Perform this action by running

drush updatedb

 

Permissions

If completed, then change the permissions that were altered at the start

chmod -R 755 {path}/web/sites/default
chmod 644 {path}/web/sites/default/*settings.php
chmod 644 {path}/web/sites/default/*services.yml

 

Review the Status Report

If you have any issues, read through the Errors / issues below.  You might be experiencing similar issues to us.

Otherwise, if all going well, then let's cross check status report (Admin > Reports > Status Report).

 

Status Report - Errors

The first batch of errors:

Area Notes or details
Search API The following search servers are not available: General, Related
Solr Server General Solr not reachable
Solr server General is not reachable.
Solr Server Related Solr not reachable
Solr server Related is not reachable.

The Solr errors I'll leave as there related to the server.

 

Status Report - warnings

Area Notes or details Solution
Color Field library: jQuery Simple Color

Missing

If you want to use the Simple Color widget, you must download the jQuery Simple Color library and copy it to /app/web/libraries/jquery-simple-color/

Download library from https://github.com/recurser/jquery-simple-color
Color Field library: Spectrum

Missing

If you want to use the Spectrum widget, you must download the Spectrum Library and copy it to /app/web/libraries/spectrum/

Download the library from https://github.com/bgrins/spectrum
Configuration files

Protection disabled

  • The file sites/default/settings.php is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.
  • The file sites/default/settings.local.php is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.
  • The file sites/default/services.yml is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.

The permissions noted above are correct.

If you see this error, then check if hardening has been activated.  If so, you'll need to add to your settings.php file the following line

$settings['skip_permissions_hardening'] = FALSE;
Deprecated modules enabled Deprecated modules found: Activity Tracker. Uninstall listed modules
Media It is potentially insecure to display oEmbed content in a frame that is served from the same domain as your main Drupal site, as this may allow execution of third-party code. You can specify a different domain for serving oEmbed content here.  
SameSite cookie attribute

Not set

This attribute should be explicitly set to Lax, Strict or None. If set to None then the request must be made via HTTPS. See PHP documentation

 
Transaction isolation level

REPEATABLE-READ

The recommended level for Drupal is "READ COMMITTED". See the setting MySQL transaction isolation level page for more information.

 

 

 

Errors / issues

Theme issue

When working on updating a custom theme from Drupal 9 to Drupal 10, the theme used Stable as a base theme.  However, this needs to be changed to Stable9 to work in Drupal 10.  However, I came across a curious issue I had the following error.

Drupal\Core\Theme\MissingThemeDependencyException: Base theme stable9 has not been installed. in Drupal\Core\Theme\ThemeInitialization->getActiveThemeByName() (line 122 of core/lib/Drupal/Core/Theme/ThemeInitialization.php)

To resolve this error, I manually installed Stable9 using Drush

drush theme:enable stable9

Response

 [success] Successfully installed theme: stable9

 

Attempting to run drush updb again.

I had the following warning:

 [warning]  (Currently using Protected forms Total of 0 submissions containing spam patterns [1] have been rejected.

[1] http://default/admin/config/content/protected_forms
)
 [error]   (Currently using Removed core theme You must add the following contributed theme and reload this page.
 * Stable [1]

This theme is installed on your site but is no longer provided by Core.
For more information read the documentation on deprecated themes. [2]

[1] https://www.drupal.org/project/stable
[2] https://www.drupal.org/node/3223395#s-recommendations-for-deprecated-themes
)
Requirements check reports errors. Do you wish to continue? (yes/no) [yes]:

Given I was confident with my preparation, I responded yes so the database would be updated.

 

 Requirements check reports errors. Do you wish to continue? (yes/no) [yes]:
 >

 ------------------ ----------- --------------- --------------------------------
  Module             Update ID   Type            Description
 ------------------ ----------- --------------- --------------------------------
  system             10100       hook_update_n   10100 - Remove the year 2038
                                                 date limitation.
  block_content      10100       hook_update_n   10100 - Update entity
                                                 definition to handle revision
                                                 routes.
  block_content      10200       hook_update_n   10200 - Remove the unique
                                                 values constraint from block
                                                 content info fields.
  comment            10100       hook_update_n   10100 - Remove the year 2038
                                                 date limitation.
  dblog              10100       hook_update_n   10100 - Remove the year 2038
                                                 date limitation.
  dblog              10101       hook_update_n   10101 - Converts the 'wid' of
                                                 the 'watchdog' table to a big
                                                 integer.
  history            10100       hook_update_n   10100 - Remove the year 2038
                                                 date limitation.
  openai             10001       hook_update_n   10001 - Disable the openai_api
                                                 module.
  statistics         10100       hook_update_n   10100 - Remove the year 2038
                                                 date limitation.
  tracker            10100       hook_update_n   10100 - Remove the year 2038
                                                 date limitation.
  user               10000       hook_update_n   10000 - Remove non-existent
                                                 permissions created by
                                                 migrations.
  block_content      block_li    post-update     Update block_content 'block
                     brary_vi                    library' view permission.
                     ew_permi
                     ssion
  block_content      move_cus    post-update     Moves the custom block library
                     tom_bloc                    to Content.
                     k_librar
                     y
  block_content      sort_per    post-update     Update permissions for users
                     missions                    with "administer blocks"
                                                 permission.
  ckeditor5          code_blo    post-update     Updates Text Editors using
                     ck                          CKEditor 5 Code Block.
  ckeditor5          plugins_    post-update     Updates Text Editors using
                     settings                    CKEditor 5 to sort plugin
                     _export_                    settings by plugin key.
                     order
  editor             image_la    post-update     Enable filter_image_lazy_load
                     zy_load                     if editor_file_reference is
                                                 enabled.
  file               add_perm    post-update     Grant all non-anonymous roles
                     issions_                    the 'delete own files'
                     to_roles                    permission.
  media              oembed_l    post-update     Add the oEmbed loading
                     oading_a                    attribute setting to field
                     ttribute                    formatter instances.
  metatag            v2_01_ch    post-update     Convert all fields to use JSON
                     ange_fie                    storage.
                     lds_to_j
                     son
  metatag            v2_02_re    post-update     Remove meta tags entity values
                     move_ent                    that were removed in v2.
                     ity_valu
                     es
  metatag            v2_03_re    post-update     Remove meta tags from default
                     move_con                    configurations that were
                     fig_valu                    removed in v2.
                     es
  metatag            v2_04_un    post-update     Uninstall submodule(s)
                     install_                    deprecated in v2: GooglePlus.
                     modules
  metatag            v2_05_tw    post-update     Replace deprecatedremoved
                     itter_ty                    Twitter Card "type" values.
                     pe_chang
                     es
  responsive_image   image_lo    post-update     Add the image loading settings
                     ading_at                    to responsive image field
                     tribute                     formatter instances.
  responsive_image   order_mu    post-update     Re-order mappings by
                     ltiplier                    breakpoint ID and descending
                     _numeric                    numeric multiplier order.
                     ally
  system             enable_p    post-update     Enable the password
                     assword_                    compatibility module.
                     compatib
                     ility
  system             linkset_    post-update     Add new menu linkset endpoint
                     settings                    setting.
  system             timestam    post-update     Update timestamp formatter
                     p_format                    settings for entity view
                     ter                         displays.
  text               allowed_    post-update     Add allowed_formats setting to
                     formats                     existing text fields.
  views              boolean_    post-update     Update Views config schema to
                     custom_t                    make boolean custom titles
                     itles                       translatable.
  views              fix_revi    post-update     Fix '-revision_id' replacement
                     sion_id_                    token syntax.
                     part
  views              oembed_e    post-update     Add eager load option to all
                     ager_loa                    oembed type field
                     d                           configurations.
  views              responsi    post-update     Add lazy load options to all
                     ve_image                    responsive image type field
                     _lazy_lo                    configurations.
                     ad
  views              timestam    post-update     Update timestamp formatter
                     p_format                    settings for views.
                     ter
  webform            ckeditor    post-update     Move from custom CKEditor to
                                                 hidden 'webform_default' text
                                                 format.
  webform            ckeditor    post-update     Issue #3351348:
                     01                          '#multiple__no_items_message'
                                                 added to every field.
  webform            confirma    post-update     #3335924: Allow the
                     tion_pag                    confirmation page to include
                     e_noinde                    robots noindex meta tag.
                     x
  webform            deprecat    post-update     #3254570: Move jQuery UI
                     e_jquery                    datepicker support into
                     _ui_date                    dedicated deprecated module.
                     picker
  webform            deprecat    post-update     Issue #3247475: Location field
                     e_locati                    Algolia Places sunsetting May
                     on_place                    31, 2022.
                     s
  webform            multiple    post-update     Issue #3339769: Improve
                     _categor                    Webform categorization to
                     ies                         support assigning multiple
                                                 categories and default
                                                 categories.
 ------------------ ----------- --------------- --------------------------------

 Do you wish to run the specified pending updates? (yes/no) [yes]:
 >

>  [notice] Update started: block_content_update_10100
>  [notice] Added revision routes to Content block entity type.
>  [notice] Update completed: block_content_update_10100
>  [notice] Update started: dblog_update_10100
>  [notice] Update completed: dblog_update_10100
>  [notice] Update started: system_update_10100
>  [notice] Update completed: system_update_10100
>  [notice] Update started: block_content_update_10200
>  [notice] Update completed: block_content_update_10200
>  [notice] Update started: comment_update_10100
>  [notice] Update completed: comment_update_10100
>  [notice] Update started: dblog_update_10101
>  [notice] Update completed: dblog_update_10101
>  [notice] Update started: history_update_10100
>  [notice] Update completed: history_update_10100
>  [notice] Update started: openai_update_10001
>  [notice] Update completed: openai_update_10001
>  [notice] Batch process has consumed in excess of 60% of available memory. Starting new thread
>  [notice] Update started: statistics_update_10100
>  [notice] Update completed: statistics_update_10100
>  [notice] Update started: tracker_update_10100
>  [notice] Update completed: tracker_update_10100
>  [notice] Update started: user_update_10000
>  [notice] Update completed: user_update_10000
>  [notice] The file assets://css was not deleted because it does not exist.
>  [notice] Batch process has consumed in excess of 60% of available memory. Starting new thread
>  [notice] Update started: block_content_post_update_block_library_view_permission
>  [notice] Update completed: block_content_post_update_block_library_view_permission
>  [notice] Update started: block_content_post_update_move_custom_block_library
>  [notice] Update completed: block_content_post_update_move_custom_block_library
>  [notice] Update started: block_content_post_update_sort_permissions
>  [notice] Update completed: block_content_post_update_sort_permissions
>  [notice] Update started: ckeditor5_post_update_code_block
>  [notice] Update completed: ckeditor5_post_update_code_block
>  [notice] Update started: ckeditor5_post_update_plugins_settings_export_order
>  [notice] Update completed: ckeditor5_post_update_plugins_settings_export_order
>  [notice] Update started: editor_post_update_image_lazy_load
>  [notice] Update completed: editor_post_update_image_lazy_load
>  [notice] Update started: file_post_update_add_permissions_to_roles
>  [notice] Update completed: file_post_update_add_permissions_to_roles
>  [notice] Update started: media_post_update_oembed_loading_attribute
>  [notice] Update completed: media_post_update_oembed_loading_attribute
>  [notice] Update started: metatag_post_update_v2_01_change_fields_to_json
>  [notice] There were no overridden Metatag records that needed to be updated to store the data using JSON.
>  [notice] Update completed: metatag_post_update_v2_01_change_fields_to_json
>  [notice] Update started: metatag_post_update_v2_02_remove_entity_values
>  [notice] There were no Metatag records to update.
>  [notice] Update completed: metatag_post_update_v2_02_remove_entity_values
>  [notice] Update started: metatag_post_update_v2_03_remove_config_values
>  [notice] Removed meta tags from the node Metatag configuration.
>  [notice] Update completed: metatag_post_update_v2_03_remove_config_values
>  [notice] Update started: metatag_post_update_v2_04_uninstall_modules
>  [notice] Metatag: Google Plus has been uninstalled.
>  [notice] Update completed: metatag_post_update_v2_04_uninstall_modules
>  [notice] Batch process has consumed in excess of 60% of available memory. Starting new thread
>  [notice] Update started: metatag_post_update_v2_05_twitter_type_changes
>  [notice] Update completed: metatag_post_update_v2_05_twitter_type_changes
>  [notice] Update started: responsive_image_post_update_image_loading_attribute
>  [notice] Update completed: responsive_image_post_update_image_loading_attribute
>  [notice] Update started: responsive_image_post_update_order_multiplier_numerically
>  [notice] Update completed: responsive_image_post_update_order_multiplier_numerically
>  [notice] Update started: system_post_update_enable_password_compatibility
>  [notice] Update completed: system_post_update_enable_password_compatibility
>  [notice] Batch process has consumed in excess of 60% of available memory. Starting new thread
>  [notice] Update started: system_post_update_linkset_settings
>  [notice] Update completed: system_post_update_linkset_settings
>  [notice] Update started: system_post_update_timestamp_formatter
>  [notice] Update completed: system_post_update_timestamp_formatter
>  [notice] Update started: text_post_update_allowed_formats
>  [notice] Update completed: text_post_update_allowed_formats
>  [notice] Update started: views_post_update_boolean_custom_titles
>  [notice] Update completed: views_post_update_boolean_custom_titles
>  [notice] Update started: views_post_update_fix_revision_id_part
>  [notice] Update completed: views_post_update_fix_revision_id_part
>  [notice] Update started: views_post_update_oembed_eager_load
>  [notice] Update completed: views_post_update_oembed_eager_load
>  [notice] Update started: views_post_update_responsive_image_lazy_load
>  [notice] Update completed: views_post_update_responsive_image_lazy_load
>  [notice] Update started: views_post_update_timestamp_formatter
>  [notice] Update completed: views_post_update_timestamp_formatter
>  [notice] Update started: webform_post_update_ckeditor
>  [notice] Update completed: webform_post_update_ckeditor
>  [notice] Update started: webform_post_update_ckeditor01
>  [notice] Update completed: webform_post_update_ckeditor01
>  [notice] Update started: webform_post_update_confirmation_page_noindex
>  [notice] Update completed: webform_post_update_confirmation_page_noindex
>  [notice] Update started: webform_post_update_deprecate_jquery_ui_datepicker
>  [notice] Update completed: webform_post_update_deprecate_jquery_ui_datepicker
>  [notice] Update started: webform_post_update_deprecate_location_places
>  [notice] Update completed: webform_post_update_deprecate_location_places
>  [notice] Update started: webform_post_update_multiple_categories
>  [notice] Update completed: webform_post_update_multiple_categories
 [success] Finished performing updates.
 [notice] The file assets://css was not deleted because it does not exist.
 [notice] The file assets://js was not deleted because it does not exist.

 

Time to clear the database cache.

drush cr

Response

 [notice] The file assets://css was not deleted because it does not exist.
 [notice] The file assets://js was not deleted because it does not exist.
 [success] Cache rebuild complete.

Looking ok.  However, I need to investigate the file assets notice.

 

Working through errors

Using Drush, you can query the error log with watchdog

 

 -------- -------------- ------ ---------- ----------------------------------------------------------------
  ID       Date           Type   Severity   Message
 -------- -------------- ------ ---------- ----------------------------------------------------------------
  302761   18/Jul 23:20   php    Error      Error: Call to undefined function render() in
                                            bales_preprocess_page() (line 207 of
                                            /var/www/vhosts/{domain}/themes/custom/{theme}/{theme}.th
                                            eme).

 

Render() issue

Error: Call to undefined function render() in hook_preprocess_page() (line 193 of themes/custom/{theme}/{theme}.theme).

Existing code

$variables['menu_global_navigation'] = render($render_header);

or

$variables['menu_global_navigation'] = drupal_render($render_header);

Change to

$variables['menu_global_navigation'] = \Drupal::service('renderer')->render($render_header);

 

Entity query

Drupal\Core\Entity\Query\QueryException: Entity queries must explicitly set whether the query should be access checked or not. See Drupal\Core\Entity\Query\QueryInterface::accessCheck(). in Drupal\Core\Entity\Query\Sql\Query->prepare() (line 141 of core/lib/Drupal/Core/Entity/Query/Sql/Query.php).

Not a fan of this error response.  Letting the developer very little detail of where the error has occurred.   

How to resolve, check where you have added queries and adding ->accessCheck(FALSE) to your queries, so the warnings no longer appear.

Therefore, the ugliness of adding accessCheck(FALSE) to most of the entity queries and making developers spend time adding it to existing code.  As noted, not a fan having where developers are wasting hours of time chasing non-informative bugs because they forgot that queries were assuming accessCheck(TRUE) by default.

Example in my code

$bids = \Drupal::entityTypeManager()
        ->getStorage('block_content')
        ->getQuery()
        ->condition('type', $type)
        ->execute();

Change to

$bids = \Drupal::entityTypeManager()
        ->getStorage('block_content')
        ->getQuery()
        ->accessCheck(FALSE)
        ->condition('type', $type)
        ->execute();

 

file_create_url()

Error: Call to undefined function file_create_url() 

To solve this Drupal 10 error change the following, from

$image_path = file_create_url($uri);

Change to

$image_path = \Drupal::service('file_url_generator')->generateAbsoluteString($uri);

 

Related articles