Drupal 10.4.0

Drupal Core updated from 10.3.10 to 10.4.0. I spotted the update notification and went straight in — but this time it didn't go as smoothly as usual, and the update turned into a battle of error handling and recovery.

Introduction.

Let me lay out the reasons the update didn't go smoothly this time.

  1. Incomplete update processing caused by inadequate PHP memory limit settings
  2. HTTP ERROR 500 caused by Bootstrap5 failing to load
  3. Translation errors caused by mismatched Entity and Field definitions

There were three main problems, and I worked through each one to identify the cause. The root cause was the incomplete update processing triggered by insufficient PHP memory, though dependencies related to the core program changes from 10.3.x to 10.4 may also have played a part.

"As an aside — Drupal CMS is due for release and will be supported from 11.1.x. Since 10.4.x is also being developed with an eye toward updating to 11.1.x, the fact that themes and modules haven't fully caught up may also be a contributing factor."

1. The incomplete update issue.

The following steps were taken to address the incomplete update caused by PHP memory limit exhaustion and the resulting configuration file issues.

Issues encountered during the Drupal Core 10.4.0 update

  1. PHP memory limit was set to 256MB.
  2. composer update timed out
  3. Changed PHP memory limit to 1024MB
  4. Attempted the update again
  5. Installation did not proceed
  6. Identified the cause of the failed installation
  7. Composer shows 10.4.0 installation complete
  8. Drush and admin panel still showing 10.3.10
  9. Root cause identified
  10. composer.lock not updating correctly
  11. Updated composer.lock
  12. drupal/core not switching to the latest version
  13. Rebuilt drupal/core
  14. Update complete

2. HTTP ERROR 500.

The Drupal Core update completed, but HTTP ERROR 500 appeared and both the public pages and admin panel became inaccessible. Bootstrap not loading correctly was the cause — the vendor directory likely had corrupted dependencies or was referencing old files, so the fix involved repairing the vendor files.

Errors after the update completed

  1. HTTP ERROR 500 appeared and pages would not display.
  2. Fatal Error caused by autoload.php not being found
  3. Resolved by completely regenerating the vendor directory

3. Entity and Field definition mismatch.

The public pages were successfully restored, but errors appeared about mismatched entity and field definitions related to translations. The vendor directory repair was likely what caused the entity and field mismatch, so running an entity update resolved it.

Errors displayed

  1. Entity field definitions
    Entity and field definitions are mismatched
    The following changes were detected in entity type and field definitions.
  2. Custom menu links
    Translation source field needs to be uninstalled.
    Translation outdated field needs to be uninstalled.
    Translation author field needs to be uninstalled.
    Translation status field needs to be uninstalled.
    Translation created field needs to be uninstalled.
  3. Content
    Translation source field needs to be uninstalled.
    Translation outdated field needs to be uninstalled.
  4. Taxonomy term
    Translation source field needs to be uninstalled.
    Translation outdated field needs to be uninstalled.
    Translation author field needs to be uninstalled.
    Translation created field needs to be uninstalled.

Fix

  1. Likely caused by the vendor directory regeneration — resolved by running an entity update

The three errors above all occurred and were resolved, completing the update successfully.

Error investigation and response.

Here's a detailed walkthrough of the investigation and response for each error. Working through them involved Composer and Drush commands I hadn't used before.

1. Drupal 10.3.10 >10.4.0.

Updating Drupal Core from 10.3.10 to 10.4.0 with composer update.

1-1-1. Addressing PHP memory exhaustion causing the timeout.

// Update Drupal
$ sudo composer update "drupal/core-*" --with-all-dependencies
// Timed out before installation could complete. Stopped and identified the cause.
// PHP memory was set to 256MB
----- Change PHP memory to 1024MB -----
// Check PHP ini location
$ php --ini
Configuration File (php.ini) Path: /opt/bitnami/php/etc
Loaded Configuration File:        /opt/bitnami/php/etc/php.ini
// Change PHP memory with vim
$ sudo vim /opt/bitnami/php/etc/php.ini
// php.ini entry
// Change memory_limit from 256MB to 1024MB
memory_limit = 1024MB
// Restart server to apply settings
sudo /opt/bitnami/ctlscript.sh restart php

Result

Confirmed PHP memory change at Drupal admin > Reports > Status Report

PHP memory changed to 1024MB. Now checking the current state where the update stopped partway through.

1-1-2. Checking dependencies with Composer.

// Check packages available for update in Drupal Core and modules
$ sudo composer outdated drupal/*
// List dependency tree for installed packages
$ sudo composer show -t
// Simulate the post-update state without applying any changes
$ sudo composer update --dry-run
〜〜〜〜〜
Nothing to modify in lock file
〜〜〜〜〜
Nothing to install, update or remove
〜〜〜〜〜

Result

No issues detected

1-2. drupal-check.

Let's run a dependency check with drupal-check.

  1. drupal-check scans Drupal code and dependencies to detect issues.
    drupal-check .
  2. drupal-check . puts a heavy load on the server and may cause it to stop, so check your environment and run it in a local or staging environment if at all possible.
  3. Running drupal-check . may freeze the server under load, requiring a forced server reset. Do not use it unless you have the authority to reset the server.

1-2-1. Install drupal-check.

// Install drupal-check
$ composer global require mglaman/drupal-check
// Confirm installation
$ drupal-check --version
// Installation completed successfully
〜〜〜〜〜
Nothing to modify in lock file
〜〜〜〜〜
Nothing to install, update or remove
〜〜〜〜〜
// Check installation location
$ composer global config home
〜〜〜〜〜
/home/bitnami/.config/composer
〜〜〜〜〜
// Run drupal-check
$ /home/bitnami/.config/composer/vendor/bin/drupal-check .
----- Reference -----
$ drupal-check .
If you want to run it with the short form, add it to PATH.
// Add to $PATH
$ export PATH="$PATH:/home/bitnami/.config/composer/vendor/bin"
// Apply settings
$ source ~/.bashrc

Result

drupal-check setup is complete.

Running drupal-check. I ran $ drupal-check . but it froze partway through, requiring a server restart via Lightsail.

1-2-2. Running drupal-check .

$ drupal-check .
〜〜〜〜〜
$ /home/bitnami/.config/composer/vendor/bin/drupal-check . --memory-limit=1024M
PHP Deprecated:  The drupal_root parameter is deprecated. Remove it from your configuration. Drupal Root is discovered automatically. in /home/bitnami/.config/composer/vendor/mglaman/phpstan-drupal/src/Drupal/DrupalAutoloader.php on line 92
Deprecated: The drupal_root parameter is deprecated. Remove it from your configuration. Drupal Root is discovered automatically. in /home/bitnami/.config/composer/vendor/mglaman/phpstan-drupal/src/Drupal/DrupalAutoloader.php on line 92
   260/26805 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░]   0%
 // Froze here
 
 With the process stuck, checking the Lightsail management console.
 // CPU load exceeds 60%.
 // The public site has become inaccessible.
 // Forced a restart from the Lightsail management console

Result

Abandoned drupal-check due to the high server load.

Running drupal-check . on a production server puts too much load on it, so I'm abandoning the approach.

2. Checking the situation.

Checking the current state after the failed update.

2-1-1. Attempting the update again.

// Clear cache
$ drush cr
// Clear Composer cache
$ sudo composer clear-cache
// Try the update again.
$ sudo composer update "drupal/core-*" --with-all-dependencies
〜〜〜〜〜
Gathering patches for root package.
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Writing lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
Generating autoload files
46 packages you are using are looking for funding.
Use the composer fund command to find out more!
No security vulnerability advisories found.
〜〜〜〜〜
// Nothing to modify in lock file / Nothing to install, update or remove — update not applied.

Result

Shows as already up to date and the update won't apply. The admin panel still shows Drupal 10.3.10.

Checking the configuration.

2-1-2. Checking composer.json and re-attempting the update

// composer.json
"require": {
        "composer/installers": "^2.0",
        "drupal/bootstrap5": "^4.0",
        "drupal/captcha": "^2.0",
        "drupal/core-composer-scaffold": "^10.3",
        "drupal/core-project-message": "^10.3",
        "drupal/core-recommended": "^10.3",
        "drupal/core-vendor-hardening": "^10.3",
----- (remainder omitted) -----
// Changed "^10.3" to "^10.4" just to be safe
"require": {
        "composer/installers": "^2.0",
        "drupal/bootstrap5": "^4.0",
        "drupal/captcha": "^2.0",
        "drupal/core-composer-scaffold": "^10.4",
        "drupal/core-project-message": "^10.4",
        "drupal/core-recommended": "^10.4",
        "drupal/core-vendor-hardening": "^10.4",
----- (remainder omitted) -----
// Try specifying the version explicitly for the update.
$ sudo composer require drupal/core-recommended:10.4.0 drupal/core-composer-scaffold:10.4.0 drupal/core-project-message:10.4.0 drupal/core-vendor-hardening:10.4.0 --update-with-all-dependencies
〜〜〜〜〜
Nothing to modify in lock file
Nothing to install, update or remove
〜〜〜〜〜
// Nothing to modify in lock file / Nothing to install, update or remove — update still not applied.

Result

Still shows as already up to date and the update won't apply.

2-2. composer.lock.

There may be version constraints remaining in composer.lock, so deleting it and running composer update again.

2-2-1. Deleting composer.lock and running composer update again.

// Delete composer.lock
$ sudo rm composer.lock
// Run the update again
$ sudo composer update
〜〜〜〜〜
Loading composer repositories with package information
Updating dependencies
Lock file operations: 99 installs, 0 updates, 0 removals
----- (omitted) -----
 - Locking drupal/core (10.4.0)
 - Locking drupal/core-composer-scaffold (10.4.0)
 - Locking drupal/core-project-message (10.4.0)
 - Locking drupal/core-recommended (10.4.0)
 - Locking drupal/core-vendor-hardening (10.4.0)
----- (omitted) -----
〜〜〜〜〜
// composer update completed successfully

Result

composer update ran successfully and drupal/core-related packages updated to 10.4.0. Checking the admin panel in this state, it still shows Drupal 10.3.10.

Checking the version with Composer and Drush.

2-2-2. Confirming the version

// Clear cache and update database
$ sudo drush cr
$ sudo drush updatedb
// Check whether the version has been updated.
$ composer show drupal/core
〜〜〜〜〜
composer show drupal/core
name     : drupal/core
descrip. : Drupal is an open source content management platform powering millions of websites and applications.
keywords :
versions : * 10.4.0
released : 2024-12-17, this week
type     : drupal-core
----- (omitted) -----
〜〜〜〜〜
// drupal/core version shows as updated to 10.4.0.
// Checking with drush st
$ drush st
〜〜〜〜〜
Drupal version   : 10.3.10
Site URI         : http://default
DB driver        : mysql
DB hostname      : 127.0.0.1
〜〜〜〜〜
// drupal/core version is still showing as 10.3.10.

Result

Drupal version shows as 10.3.10 — which doesn't match the version 10.4.0 confirmed in Composer.

3. drupal/core.

Checking whether the core directory that's actually being referenced has the correct version. Using the following command to check the contents of CHANGELOG.txt in the core directory.

3-1-1. Checking the Core directory

$ head -n 10 /opt/bitnami/drupal/core/CHANGELOG.txt
〜〜〜〜〜
New minor (feature) releases of Drupal are released every six months and
patch (bugfix) releases are released every month. More information on the
Drupal release cycle: https://www.drupal.org/core/release-cycle-overview
* For a full list of fixes in the latest release, visit:
https://www.drupal.org/latest-release
* API change records for Drupal core:
https://www.drupal.org/list-changes/drupal
〜〜〜〜〜
// No Drupal version information displayed.

Result

The absence of specific version information suggests /opt/bitnami/drupal/core may not have been updated correctly. Since Composer's output showed it updated to 10.4.0, there's a contradiction in the codebase.

Checking the Drupal Core directory.

3-1-2. Checking the Core directory version

// Check the core directory
$ ls -l /opt/bitnami/drupal/core
total 764
drwxr-xr-x  5 root root   4096 Nov 22 12:51 assets
-rw-r--r--  1 root root   7243 Nov 22 12:51 authorize.php
-rw-r--r--  1 root root    399 Nov 22 12:51 CHANGELOG.txt
-rw-r--r--  1 root root   7077 Nov 22 12:51 composer.json
// Nov 22 dates suggest this is 10.3.10.
// Check the source files
$ ls -l /opt/bitnami/drupal/vendor/drupal/core
total 780
drwxr-xr-x  5 root root   4096 Dec 17 22:18 assets
-rw-r--r--  1 root root   7243 Dec 17 22:18 authorize.php
-rw-r--r--  1 root root    399 Dec 17 22:18 CHANGELOG.txt
-rw-r--r--  1 root root   7077 Dec 17 22:18 composer.json
// Dec 17 dates suggest this is 10.4.0.

Result

Checking each directory's contents: /opt/bitnami/drupal/core dates from Nov 22 — indicating 10.3.10. /opt/bitnami/drupal/vendor/drupal/core dates from Dec 17 — confirming 10.4.0.

/opt/bitnami/drupal/core is holding onto the old files, so Drupal is referencing the old code — which is why the correct version isn't showing in the admin panel or Drush.

Deleting /opt/bitnami/drupal/core and creating a symbolic link to point to the correct code (vendor/drupal/core).

3-1-3. Rebuilding /opt/bitnami/drupal/core

// Delete opt/bitnami/drupal/core
$ sudo rm -rf /opt/bitnami/drupal/core
// Create a symbolic link pointing to vendor/drupal/core.
sudo ln -s /opt/bitnami/drupal/vendor/drupal/core /opt/bitnami/drupal/core
// Clear cache
$ drush cr
// Update database
$ drush updatedb
〜〜〜〜〜
 Module   Update ID   Type            Description
 -------- ----------- --------------- -------------------------------------
  system   10400       hook_update_n   10400 - Equivalent update to 11102.
 -------- ----------- --------------- -------------------------------------
 ┌ Do you wish to run the specified pending updates? ───────────┐
 │ Yes                                                          │
 └──────────────────────────────────────────────────────────────┘
>  [notice] Update started: system_update_10400
>  [notice] Update completed: system_update_10400
 [success] Finished performing updates.
〜〜〜〜〜
// Database updated to 10.4.0.
// Restart the web server to apply changes.
$ sudo /opt/bitnami/ctlscript.sh restart
Restarting services..

Result

Once the restart is complete and the terminal reconnects, checking the version with Drush.

Confirming the Drupal version.

3-1-4. Confirming the Drupal version

// Check the Drupal version.
$ drush st
〜〜〜〜〜
 [warning] Undefined array key "bootstrap5" ThemeHandler.php:74
Drupal version   : 10.4.0
Site URI         : http://default
DB driver        : mysql
DB hostname      : 127.0.0.1
----- (omitted) -----
〜〜〜〜〜
// Update complete, but the following error is appearing.
 [warning] Undefined array key "bootstrap5" ThemeHandler.php:74

Result

Updated to Drupal 10.4.0.

[warning] Undefined array key "bootstrap5" ThemeHandler.php:74

A Bootstrap5 error is appearing.

4. The Bootstrap5 error.

The Drupal 10.3.10 > 10.4.0 update completed, but Bootstrap5 errors are appearing in the terminal, and checking the site shows HTTP ERROR 500 — the public pages and admin panel are no longer accessible. Time to resolve the HTTP ERROR 500. 

[warning] Undefined array key "bootstrap5" ThemeHandler.php:74

Checking the Apache error log.

4-1-1. Checking the Apache error log

// Apache error log
$ tail -n 50 /opt/bitnami/apache2/logs/error_log
〜〜〜〜〜
[Fri Dec 20 06:18:57.726988 2024] [authz_core:error] [pid 1054:tid 1139] [client 123.123.123.123:37826] AH01630: client denied by server configuration: /opt/bitnami/drupal/vendor/phpunit
----- (remainder omitted) -----
Got error 'PHP message: PHP Warning:  require_once(/opt/bitnami/drupal/vendor/drupal/autoload.php): Failed to open stream: No such file or directory in /opt/bitnami/drupal/vendor/drupal/core/install.php on line 38; PHP message: PHP Fatal error:  Uncaught Error: Failed opening required '/opt/bitnami/drupal/vendor/drupal/autoload.php' (include_path='.:/opt/bitnami/php/lib/php') in /opt/bitnami/drupal/vendor/drupal/core/install.php:38\nStack trace:\n#0 {main}\n  thrown in /opt/bitnami/drupal/vendor/drupal/core/install.php on line 38'
〜〜〜〜〜
// PHP Fatal error:  Uncaught Error: Failed opening required '/opt/bitnami/drupal/vendor/drupal/autoload.php' (include_path='.:/opt/bitnami/php/lib/php') in /opt/bitnami/drupal/vendor/drupal/core/install.php:38\nStack trace:\n#0 {main}\n  thrown in 

Result

A Fatal error is occurring because /opt/bitnami/drupal/vendor/drupal/autoload.php cannot be found.

Causes of the missing autoload.php

  1. Composer may not have installed dependencies correctly.
  2. The vendor directory may be incomplete or corrupted.

Completely regenerating the vendor directory.

4-1-2. Regenerating the vendor directory

// Delete the vendor directory
$ sudo rm -rf vendor
// Reinstall dependencies
$ sudo composer install
〜〜〜〜〜
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 99 installs, 0 updates, 0 removals
- Downloading composer/installers (v2.3.0)
- Downloading drupal/core-composer-scaffold (10.4.0)
----- (omitted) -----
〜〜〜〜〜
// Clear cache
$ drush cr
// HTTP 500 ERROR resolved.

Result

HTTP 500 ERROR cleared and both the public site and admin panel are displaying normally.

4-2. The Entity and Field definition mismatch issue.

Regenerating the vendor directory fixed the Bootstrap5 error, cleared the HTTP 500 ERROR, and the public site and admin panel are now displaying without issues.

However, running $ drush cr is producing the following errors, and the admin panel Reports section is also showing errors about mismatched entity and field definitions.

4-2-1. Errors appearing in $ drush cr

$ drush cr
〜〜〜〜〜
 [warning] include_once(/opt/bitnami/drupal/vendor/drupal/core/modules/announcements_feed/announcements_feed.module): Failed to open stream: No such file or directory Extension.php:153
 [warning] include_once(): Failed opening '/opt/bitnami/drupal/vendor/drupal/core/modules/announcements_feed/announcements_feed.module' for inclusion (include_path='/opt/bitnami/drupal/vendor/pear/pear_exception:/opt/bitnami/drupal/vendor/pear/console_getopt:/opt/bitnami/drupal/vendor/pear/core-minimal/src:/opt/bitnami/drupal/vendor/pear/archive_tar:.:/opt/bitnami/php/lib/php') Extension.php:153
 ----- (remainder omitted) -----
 〜〜〜〜〜

Errors in the admin panel

  1. Entity field definitions
    Entity and field definitions are mismatched
    The following changes were detected in entity type and field definitions.
  2. Custom menu links
    Translation source field needs to be uninstalled.
    Translation outdated field needs to be uninstalled.
    Translation author field needs to be uninstalled.
    Translation status field needs to be uninstalled.
    Translation created field needs to be uninstalled.

(remainder omitted)

These errors appear when mismatches are detected in entity and field definitions — they typically occur when translation-related fields are unnecessary or incorrectly configured.

  1. Changes to or uninstallation of the translation module (content_translation or interface_translation) may be affecting this.
  2. Entity and field definitions were changed during the update but have not been applied to the database.
  3. This message appears when unnecessary translation fields remain in the system.

Running the following command to fix the mismatch.

$ drush entup

This command runs an 'entity update', removing or applying unnecessary fields and entities.

4-2-2. Fixing the definition mismatch

// Update entities
$ drush entup
Command "entup" is not defined.
Command not available. // Currently unusable
-----
// Update entities
$ drush entity:updates // Currently unusable
Command not available.
// Available commands are displayed.
Command "entity:updates" is not defined.
  Did you mean one of these?
      entity-create
      entity-delete
      entity-save
      entity:create
      entity:delete
      entity:save
      locale:update
      y:update:key
      y:update:value
      yaml:update:key
      yaml:update:value
 -----
// Using locale:update
$ drush local:update
>  [notice] Checked translations for bootstrap5 (ja).
>  [notice] Checked translations for captcha (ja).
>  [notice] Checked translations for drupal (ja).
>  [notice] Checked translations for easy_breadcrumb (ja).
>  [notice] Checked translations for google_tag (ja).
>  [notice] Checked translations for metatag (ja).
>  [notice] Checked translations for recaptcha (ja).
>  [notice] Checked translations for recaptcha_v3 (ja).
>  [notice] Checked translations for simple_sitemap (ja).
>  [notice] Checked translations for smtp (ja).
>  [notice] Checked translations for token (ja).
// Definition mismatch fix complete
-----
// Clear cache
$ drush cr

Result

Errors cleared from the terminal. Admin panel error messages also gone.

5. All repairs complete.

This article ended up quite long, but Drupal Core has been successfully updated to 10.4.0 and all module and theme dependencies are running without issues. The root cause of all the time-consuming repair work this time was the PHP memory limit sitting at 256MB — it caused the 10.4.0 update to time out midway, leaving everything in an incomplete state and creating a cascade of dependency and directory issues to fix.

The fact that module additions and updates had been going smoothly meant I never noticed the PHP memory limit was still at 256MB — careless of me. On reflection though, having the update go wrong gave me the chance to re-examine Drupal's operating requirements, which was a useful outcome.

Conclude.

A minor version bump for Drupal Core turned into a much harder battle than expected — all because the operating conditions weren't properly in place. Working through the error recovery did push me to use Composer and Drush commands I'd never touched before, which ended up deepening my understanding of Drupal's structure.

I'm not an engineer and my programming knowledge is limited, but working through this error was a good reminder that Drupal is a CMS built on PHP and a database — not just a web tool. 

Having gone so long without hitting any significant errors, I'd developed something like an unconditional faith in Drupal's stability. Learning the hard way that mistakes in how you use it can lead to a lot of repair work was a valuable experience.

This incident reinforced the importance of staging, and reminded me to build a solid habit of testing thoroughly in the local environment on my MacBook before making any changes to the live site.

As an aside — while researching the errors I visited Drupal.org and noticed the site design had been updated, which led me to look at Drupal CMS, due for release in January 2025. I've installed the test version of Drupal CMS on my MacBook with the Bootstrap5 theme and have been running it.

I'm also considering migrating from Lightsail to EC2 in the near future, and plan to actively use Drupal 11.1.x and Drupal CMS to keep pace with Drupal's evolution.

Next article.

Web Design Color Scheme

While doing the 10.4.0 update I took the opportunity to make some site design changes — minor adjustments to color scheme, spacing for components and tags, and font choices. Next article covers those design changes.

Contributor
S.Takeda
Article

Powered by Drupal 11.4.2 and Bootstrap 5.0.4

Published AWS Jamstack by Drupal