Status report should warn about OPcache bug in PHP 8.1.0 to 8.1.5

Created on 17 January 2022, over 2 years ago
Updated 25 July 2023, 11 months ago

Problem/Motivation

PHP 8.1 introduces many deprecation notices that would not appear previously. In my experience, it seems that hitting one of these notices (when thrown by a contrib module) generally causes a critical error coming from Core -- Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() (line 63 of core/includes/errors.inc).. In such cases, the deprecation message is included in the stack trace:

Update: this was a core PHP bug, that was fixed in the (very) recent PHP 8.1.6 release.

The website encountered an unexpected error. Please try again later.
Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() (line 63 of core/includes/errors.inc).

_drupal_error_handler_real(8192, 'Return type of Drupal\profile\Plugin\Field\ProfileEntityFieldItemList::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice', '/var/www/html/drupal/web/core/lib/Drupal/Core/TypedData/ComputedItemListTrait.php', 121) (Line: 346)
_drupal_error_handler(8192, 'Return type of Drupal\profile\Plugin\Field\ProfileEntityFieldItemList::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice', '/var/www/html/drupal/web/core/lib/Drupal/Core/TypedData/ComputedItemListTrait.php', 121) (Line: 571)
include('/var/www/html/drupal/web/core/includes/bootstrap.inc') (Line: 571)
Composer\Autoload\includeFile('/var/www/html/drupal/vendor/composer/../../web/core/lib/Drupal/Core/Utility/Error.php') (Line: 428)
Composer\Autoload\ClassLoader->loadClass('Drupal\Core\Utility\Error') (Line: 44)
Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->on403(Object) (Line: 97)
Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onException(Object, 'kernel.exception', Object)
call_user_func(Array, Object, 'kernel.exception', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.exception') (Line: 219)
Symfony\Component\HttpKernel\HttpKernel->handleThrowable(Object, Object, 1) (Line: 91)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 67)
Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 49)
Asm89\Stack\Cors->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Fixing/patching the deprecation seems to get rid of the notice, as well as this error handler error itself. The error handler error is problematic because it turns what should be a simple notice into a critical failure. I think that what must be happening is that the deprecation is somehow short-circuiting the autoloader or something.

This is an intermittent bug that seems to appear at a frequency of every few days. So far it has only been reported due to PHP core deprecation notices (e.g. for new return types for classes like ArrayAccess). As such, the problem may be with recursive classloader calls, i.e.:

- Classloader loads class A that extends a PHP core class - PHP triggers a deprecation notices for a return type.
- Drupal error handler is invoked
- The error handler triggers autoloading of \Drupal\Core\Utility\Error
- autoloading of \Drupal\Core\Utility\Error fails (why?) -> fatal

Steps to reproduce

There are no obvious steps to reproduce, you need a module installed which triggers a PHP deprecation notice, possibly php-fpm, and it may take several days for this error to appear.

Proposed resolution

Add a hook_requirements() to all supported branches of Drupal that checks for PHP >= 8.1.0 and < 8.1.6, and suggests updating to PHP 8.1.6 due to intermittent PHP autoloading issues.

PHP 8.1.6 is so recent that a hard requirement would potentially be a barrier to running Drupal for several months, and this only happens with deprecation warnings triggered via classloading, which isn't a problem for every install.

If we detect PHP 8.1.0 through 8.1.6, we should make sure the status report warns about it. How exactly we do that varies depending on Drupal version.

In Drupal 10, PHP 8.1.0 is the minimum bootable PHP version, and 8.1.6 is now the minimum recommended version. So, if we detect a broken PHP version is running, we should change the PHP section of the status report to a warning, with this (proposed) wording:

PHP $RUNNING_VERSION has an OPcache bug that can cause fatal errors with class autoloading. This can be fixed by upgrading to PHP 8.1.6 or later.

See #110, #111, and #112 for screenshots in 9.4.x, 9.5.x, and 10.0.x, respectively.

User interface changes

Release note snippet

Needed.

πŸ“Œ Task
Status

Fixed

Version

9.4

Component
OtherΒ  β†’

Last updated about 2 hours ago

Created by

πŸ‡ΊπŸ‡ΈUnited States mrweiner

Live updates comments and jobs are added and updated live.
  • PHP 8.1

    The issue particularly affects sites running on PHP version 8.1.0 or later.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States bogdog400

    I just wanted to make a note of the fact that I had this same problem with 8.1.2-1ubuntu2.13. It went away with rebooting. Now I'm going to try to upgrade to PHP 8.1.6.

    Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() (line 63 of /var/www/html/mo2/web/core/includes/errors.inc).
    
  • πŸ‡ΊπŸ‡ΈUnited States bogdog400

    It was fixed when I first rebooted, but it appeared soon after. So I went to trying to upgrade from 8.1.2 and Ubuntu made it difficult. I was able to upgrade, but only after adding this repository:

    sudo add-apt-repository ppa:ondrej/php
    

    Apparently Ubuntu is stuck at 8.1.2.

Production build 0.69.0 2024