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.

Issue fork drupal-3258987

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mrweiner created an issue. See original summary.

patrickmichael’s picture

I think my issue is related to this issue. I am running Drupal 9.3.2 with PHP 8.1.1. It is an upgrade from 8.9.20. I do not know what triggers this. I am not sure how to reproduce. The event causes the site to the state of 'The website encountered an unexpected error.....'

Error: Call to undefined function _drupal_error_handler_real() in require_once() (line 568 of /web/core/lib/Drupal/Core/DrupalKernel.php)

#0 /web/core/lib/Drupal/Core/DrupalKernel.php(568): _drupal_error_handler()
#1 /web/core/lib/Drupal/Core/DrupalKernel.php(568): require_once()
#2 /web/core/lib/Drupal/Core/DrupalKernel.php(583): Drupal\Core\DrupalKernel->loadLegacyIncludes()
#3 /web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(46): Drupal\Core\DrupalKernel->preHandle()
#4 /web/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#5 /web/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\page_cache\StackMiddleware\PageCache->fetch()
#6 /web/core/modules/page_cache/src/StackMiddleware/PageCache.php(82): Drupal\page_cache\StackMiddleware\PageCache->lookup()
#7 /web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#8 /web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#9 /vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#10 /web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle()
#11 /web/index.php(19): Drupal\Core\DrupalKernel->handle()
#12 {main}

Any help to resolve this would be greatly appreciated.

cilefen’s picture

Status: Active » Postponed (maintainer needs more info)
Issue tags: +Needs steps to reproduce
john.glynn.davies’s picture

I upgraded to php 8.1.1 and encountered a similar issue, except in my case the missing class was:

Error: Class "Drupal\Core\Logger\RfcLogLevel" not found in /home/www/core/includes/errors.inc on line 26 #0 /webroots/www/studio/core/includes/errors.inc(60): drupal_error_levels()

But I couldn't see what the actual error was inside _drupal_error_handler_real(8192, 'Return type of ...', '/home/www/c...', 107) because it was truncated (...).

I was going mad trying to figure out how to get at that but then restarted PHP and that seemed to resolve the issue.

Hope that helps someone!

mrweiner’s picture

I saw the same as #4 while trying to figure out repro for the initial description. If not the same issue, it may be a separate but related error. Steps to recreate that were:

1. Create a new drupal installation on 7.4 with DDEV
2. Run standard install
3. Load up the site url, site loads fine
4. Update image settings to use 8.1 instead of 7.4
5. Restart the container
6. Hit the RfcLogLevel error when loading up the site
7. Restart the container and the error disappears.

gnumatrix’s picture

Thanks #4 !!

After mindlessly upgrading my Ubuntu system, PHP moved from 8.1.1 to PHP 8.1.2 and then I got this error:

Error: Call to undefined function _drupal_error_handler_real() in require_once()

And indeed, a restart of PHP was all that was needed to correct it.

systemctl restart php8.1-fpm.service

And all is well once again.

cilefen’s picture

Category: Bug report » Support request
Priority: Major » Normal

This looks like platform issues.

mrweiner’s picture

I'm tempted to reopen this, but I'll leave it be since I haven't found reliable reproduction. If anybody else lands here from google and #4 does not solve your issue, I'd encourage you to leave a comment with additional context in case there's some other underlying issue.

hansfn’s picture

It might be a platform issue, but switching to 8.1 on my service provider causes the Class "Drupal\Core\Logger\RfcLogLevel" not found error and switching back to 8.0 fixes it again. (And 7.4 works.) It would be nice if Drupal was able to recover from the situation.

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

Yes, that seems to be the issue on my side too.

cilefen’s picture

Class not found is not a deprecation notice.

mrweiner’s picture

@cilefen you're right that "class not found" is not a deprecation notice, but it seems to be coming as a result of how Drupal internally is dealing with 8.1's deprecation notices or other things being fired by 8.1 in certain scenarios. Potentially an autoloader bug that's just tough to pin down. Just wanted to clarify.

@hansfn, it sounds like restarting PHP seems to get rid of the RfcLogError specifically, so it might be worth switching to 8.1 and restarting php to see if that fixes it for you.

didier misson’s picture

Same error as Patrick Michael :
Drupal 9.3.5
PHP 8.1.2

Anonymous users seem have NO problem.

Login users have :

Call to undefined function _drupal_error_handler_real() in /core/lib/Drupal/Core/DrupalKernel.php on line 568

If I reboot the server, or restart PHP FPM, it's ok...
but error come back some minutes... or hours later...
Thanks

gillesbailleux’s picture

The error log mentioned by Didier Misson on #12:

Error : Call to undefined function _drupal_error_handler_real() dans require_once() (/home/website/public_html/web/core/lib/Drupal/Core/DrupalKernel.php ligne 568)

#0 /home/website/public_html/web/core/lib/Drupal/Core/DrupalKernel.php(568): _drupal_error_handler()
#1 /home/website/public_html/web/core/lib/Drupal/Core/DrupalKernel.php(568): require_once()
#2 /home/website/public_html/web/core/lib/Drupal/Core/DrupalKernel.php(583): Drupal\Core\DrupalKernel->loadLegacyIncludes()
#3 /home/website/public_html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(46): Drupal\Core\DrupalKernel->preHandle()
#4 /home/website/public_html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#5 /home/website/public_html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\page_cache\StackMiddleware\PageCache->fetch()
#6 /home/website/public_html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(82): Drupal\page_cache\StackMiddleware\PageCache->lookup()
#7 /home/website/public_html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#8 /home/website/public_html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#9 /home/website/public_html/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#10 /home/website/public_html/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle()
#11 /home/website/public_html/web/index.php(19): Drupal\Core\DrupalKernel->handle()
#12 {main}
cilefen’s picture

If restarting PHP helps and the error appears after some time then I am curious about the opcache versions and configurations.

didier misson’s picture

php8.1-opcache is installed
php info give me :
/etc/php/8.1/fpm/conf.d/10-opcache.ini

So opcache is enable.

; configuration for php opcache module
; priority=10
zend_extension=opcache.so

I think I simply install opcache, but not change the default option...

------------------------
Zend OPcache
Opcode Caching Up and Running
Optimization Enabled
SHM Cache Enabled
File Cache Disabled
JIT Disabled
Startup OK
Shared memory model mmap
Cache hits 39178
Cache misses 2668
Used memory 51458800
Free memory 82758928
Wasted memory 0
Interned Strings Used memory 4339752
Interned Strings Free memory 1951240
Cached scripts 2617
Cached keys 3961
Max keys 16229
OOM restarts 0
Hash keys restarts 0
Manual restarts 0

Directive Local Value Master Value
opcache.blacklist_filename no value no value
opcache.consistency_checks 0 0
opcache.dups_fix Off Off
opcache.enable On On
opcache.enable_cli Off Off
opcache.enable_file_override Off Off
opcache.error_log no value no value
opcache.file_cache no value no value
opcache.file_cache_consistency_checks On On
opcache.file_cache_only Off Off
opcache.file_update_protection 2 2
opcache.force_restart_timeout 180 180
opcache.huge_code_pages Off Off
opcache.interned_strings_buffer 8 8
opcache.jit tracing tracing
opcache.jit_bisect_limit 0 0
opcache.jit_blacklist_root_trace 16 16
opcache.jit_blacklist_side_trace 8 8
opcache.jit_buffer_size 0 0
opcache.jit_debug 0 0
opcache.jit_hot_func 127 127
opcache.jit_hot_loop 64 64
opcache.jit_hot_return 8 8
opcache.jit_hot_side_exit 8 8
opcache.jit_max_exit_counters 8192 8192
opcache.jit_max_loop_unrolls 8 8
opcache.jit_max_polymorphic_calls 2 2
opcache.jit_max_recursive_calls 2 2
opcache.jit_max_recursive_returns 2 2
opcache.jit_max_root_traces 1024 1024
opcache.jit_max_side_traces 128 128
opcache.jit_prof_threshold 0.005 0.005
opcache.lockfile_path /tmp /tmp
opcache.log_verbosity_level 1 1
opcache.max_accelerated_files 10000 10000
opcache.max_file_size 0 0
opcache.max_wasted_percentage 5 5
opcache.memory_consumption 128 128
opcache.opt_debug_level 0 0
opcache.optimization_level 0x7FFEBFFF 0x7FFEBFFF
opcache.preferred_memory_model no value no value
opcache.preload no value no value
opcache.preload_user no value no value
opcache.protect_memory Off Off
opcache.record_warnings Off Off
opcache.restrict_api no value no value
opcache.revalidate_freq 2 2
opcache.revalidate_path Off Off
opcache.save_comments On On
opcache.use_cwd On On
opcache.validate_permission Off Off
opcache.validate_root Off Off
opcache.validate_timestamps On On

patrickmichael’s picture

I can confirm behaviour similar to #12, the error returns after restarting PHP. In one case, the site was fine for quite a few days before the error returned. On other occasions, the error returned within a few hours.

Cynthia Ewer’s picture

Subscribing.

New Ubuntu server running PHP 8.1. Two out of about 15 D9 installations go offline after kernel or server updates.

Error log: AH01071: Got error 'PHP message: Error: Class "Drupal\\Component\\Utility\\Xss" not found

Solution in #6 works for me: systemctl restart php8.1-fpm.service

ConradFlashback’s picture

Same problem.
Restart PHP server works, but I think error will come back some hours or days later.
Does anyone know a definitive solution? I must change to an older PHP version?

nottaken’s picture

Following. Seeing the same issue with 9.3.5 and PHP 8.1.

cilefen’s picture

Reading this carefully there are in fact two separate issues reported:

  1. "Call to undefined function _drupal_error_handler_real()"
  2. "Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real()". Sometimes it is a different class that cannot be found (#4, #17). I assume #17 refers to errors.inc but the reporter did not specify.

Although they may share a common cause, they are different. The first is a require failure and the second one is an autoload failure.

I just want to point that out.

ConradFlashback’s picture

My #18 report is for second error: Error: Class "Drupal\Core\Utility\Error"
This is the ontopic error signaled by first reporter.

mrweiner’s picture

@ConradFlashback a middleground solution instead of downgrading php might be to set up a cron job to restart PHP on some schedule, since it sounds like that temporarily addresses the issue for some people. We haven't really figured out what's going on yet.

szato’s picture

Same error:
Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() - line 63
On Drupal 9.3.6 ; Php 8.1.2

dolst’s picture

Hello everyone, just thought I'd weigh in here. I'll try to provide as many details as possible but if I didn't think of something, I'll try my best to update in a future post. Anyway, I have a multisite Drupal installation. It started as Drupal 8 and I recently upgraded to 9. I do everything on command line and don't use composer or drush or anything like that. I have one master site and two sites under that. Everything was fine until I tried to add a new site. Any attempts to do anything in the backend like logging in or anything like that cause the dreaded "Unknown error" page which then brings down all the sites. Restarting httpd does clear this error until the next time I try to log in.
The error I get in my logs is:

 Error: Call to undefined function _drupal_error_handler_real() in <my Drupal install directory>/core/lib/Drupal/Core/DrupalKernel.php on line 568 #0
 <my Drupal install directory>/core/lib/Drupal/Core/DrupalKernel.php(568): _drupal_error_handler()\n#1 <my Drupal install directory>/core/lib/Drupal/Core/DrupalKernel.php(568): require_once()\n#2
 <my Drupal install directory>/core/lib/Drupal/Core/DrupalKernel.php(583): Drupal\\Core\\DrupalKernel->loadLegacyIncludes()\n#3
 <my Drupal install directory>/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(46): Drupal\\Core\\DrupalKernel->preHandle()\n#4
 <my Drupal install directory>/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\\Core\\StackMiddleware\\KernelPreHandle->handle()\n#5
 <my Drupal install directory>/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\\page_cache\\StackMiddleware\\PageCache->fetch()\n#6
 <my Drupal install directory>/core/modules/page_cache/src/StackMiddleware/PageCache.php(82): Drupal\\page_cache\\StackMiddleware\\PageCache->lookup()\n#7
 <my Drupal install directory>/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\\page_cache\\StackMiddleware\\PageCache->handle()\n#8
 <my Drupal install directory>/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\\Core\\StackMiddleware\\ReverseProxyMiddleware->handle()\n#9
 <my Drupal install directory>/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\\Core\\StackMiddleware\\NegotiationMiddleware->handle()\n#10
 <my Drupal install directory>/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\\StackedHttpKernel->handle()\n#11 <my Drupal install directory>/index.php(19): Drupal\\Core\\DrupalKernel->handle()\n#12 {main}, referer: https://<my Drupal site hostname>/contact

I am running Drupal 9.3.6 on PHP 8.1.3. I only get this error (repeatedly) after adding a new site. Restarting httpd will clear it until I go to log in to a site. After restoring my Drupal installation with only the 3 original sites (and restarting httpd), everything runs fine. Not sure how much this will help, but hopefully it's another piece of the puzzle.

Surf Wisely.

_gramur’s picture

I can confirm I've been experiencing the same issues with PHP 8.1 as well. Restarting PHP solves the problem but can be problematic if running multiple Drupal instances on the same server sharing the same PHP resources. For example restarting PHP can bring 1 site back up while bringing down another one. Multiple PHP restarts solves this problem.

borisbarowski’s picture

I have the same issue, a site that was working well on PHP7.3 is now broken (after a while, not immediately after apache restart) on PHP8.1.3 using Drupal 9.3.6. Maybe it's the system, but I don't see it. Opcache is enabled and Up and Running

issue is the same

Error: Call to undefined function _drupal_error_handler_real() in require_once() (regel 568 van /srv/www/wu/web/core/lib/Drupal/Core/DrupalKernel.php)

The first error I get in the logs is related to a deprecated function
Deprecated function: Return type of Drupal\google_analytics\Component\Render\GoogleAnalyticsJavaScriptSnippet::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in include() (regel 10 van /srv/www/wu/web/modules/contrib/google_analytics/src/Component/Render/GoogleAnalyticsJavaScriptSnippet.php)

Open to provide any information required to advance this issue.

szato’s picture

Status: Postponed (maintainer needs more info) » Needs review

We are using media image as a featured image for articles and if we uploaded a new image file with "Add media" on the node add page, we got an ajax error with empty message - related issue: Uncaught Drupal.AjaxError with empty response text.

Our backtrace error message (related to search_api):

Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() (line 63 of /var/www/.../web/core/includes/errors.inc)
#0 /var/www/.../web/core/includes/bootstrap.inc(346): _drupal_error_handler_real()
#1 /var/www/.../vendor/composer/ClassLoader.php(571): _drupal_error_handler()
#2 /var/www/.../vendor/composer/ClassLoader.php(571): include('/var/www/...')
#3 /var/www/.../vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile()
#4 /var/www/.../web/modules/contrib/search_api/src/LoggerTrait.php(75): Composer\Autoload\ClassLoader->loadClass()
#5 /var/www/.../web/modules/contrib/search_api/src/Plugin/search_api/datasource/ContentEntity.php(1165): Drupal\search_api\Plugin\search_api\datasource\ContentEntity->logException()

We are on Drupal 9.3.6; Php 8.1.2 and nginx/1.18.0

For us this nginx settings solved the issue:
client_body_buffer_size 8m;

cilefen’s picture

Status: Needs review » Active

That is quite interesting. Some respondents are using Apache, so there are probably more pathways. We may be looking at a newly undocumented web server requirement.

ConradFlashback’s picture

There any update for this?

Today another crash solved restarding PHP. But it's impossible manage this.

My log is little different from first post. Error from line 26,

Error: Class "Drupal\\Core\\Logger\\RfcLogLevel" not found in /data/www/*/htdocs/web/core/includes/errors.inc on line 26 #0 /data/www/*/htdocs/web/core/includes/errors.inc(60): drupal_error_levels()\n#1 /data/www/*/htdocs/web/core/includes/bootstrap.inc(346): _drupal_error_handler_real()\n#2 /data/www/*/htdocs/vendor/composer/ClassLoader.php(571): _drupal_error_handler()\n#3 /data/www/*/htdocs/vendor/composer/ClassLoader.php(571): include('...')\n#4 /data/www/*/htdocs/vendor/composer/ClassLoader.php(428): Composer\\Autoload\\includeFile()\n#5 /data/www/*/htdocs/web/core/lib/Drupal/Core/Logger/LoggerChannelFactory.php(34): Composer\\Autoload\\ClassLoader->loadClass()\n#6 /data/www/*/htdocs/web/modules/contrib/metatag/src/MetatagManager.php(88): Drupal\\Core\\Logger\\LoggerChannelFactory->get()\n#7 /data/www/*/htdocs/web/core/lib/Drupal/Component/DependencyInjection/Container.php(262): Drupal\\metatag\\MetatagManager->__construct()\n#8 /data/www/*/htdocs/web/core/lib/Drupal/Component/DependencyInjection/Container.php(176): Drupal\\Component\\DependencyInjection\\Container->createService()\n#9 /data/www/*/htdocs/web/core/lib/Drupal.php(198): Drupal\\Component\\DependencyInjection\\Container->get()\n#10 /data/www/*/htdocs/web/modules/contrib/metatag/metatag.module(492): Drupal::service()\n#11 /data/www/*/htdocs/web/modules/contrib/metatag/metatag.module(298): metatag_get_tags_from_route()\n#12 /data/www/*/htdocs/web/modules/contrib/metatag/metatag.module(244): _metatag_remove_duplicate_entity_tags()\n#13 /data/www/*/htdocs/web/core/lib/Drupal/Core/Extension/ModuleHandler.php(539): metatag_entity_view_alter()\n#14 /data/www/*/htdocs/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(305): Drupal\\Core\\Extension\\ModuleHandler->alter()\n#15 /data/www/*/htdocs/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(239): Drupal\\Core\\Entity\\EntityViewBuilder->buildMultiple()\n#16 [internal function]: Drupal\\Core\\Entity\\EntityViewBuilder->build()\n#17 /data/www/*/htdocs/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(101): call_user_func_array()\n#18 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(772): Drupal\\Core\\Render\\Renderer->doTrustedCallback()\n#19 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(363): Drupal\\Core\\Render\\Renderer->doCallback()\n#20 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(201): Drupal\\Core\\Render\\Renderer->doRender()\n#21 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(241): Drupal\\Core\\Render\\Renderer->render()\n#22 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(564): Drupal\\Core\\Render\\MainContent\\HtmlRenderer->Drupal\\Core\\Render\\MainContent\\{closure}()\n#23 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(242): Drupal\\Core\\Render\\Renderer->executeInRenderContext()\n#24 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(132): Drupal\\Core\\Render\\MainContent\\HtmlRenderer->prepare()\n#25 /data/www/*/htdocs/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\\Core\\Render\\MainContent\\HtmlRenderer->renderResponse()\n#26 [internal function]: Drupal\\Core\\EventSubscriber\\MainContentViewSubscriber->onViewRenderArray()\n#27 /data/www/*/htdocs/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func()\n#28 /data/www/*/htdocs/vendor/symfony/http-kernel/HttpKernel.php(163): Drupal\\Component\\EventDispatcher\\ContainerAwareEventDispatcher->dispatch()\n#29 /data/www/*/htdocs/vendor/symfony/http-kernel/HttpKernel.php(80): Symfony\\Component\\HttpKernel\\HttpKernel->handleRaw()\n#30 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\\Component\\HttpKernel\\HttpKernel->handle()\n#31 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\\Core\\StackMiddleware\\Session->handle()\n#32 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\\Core\\StackMiddleware\\KernelPreHandle->handle()\n#33 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\\page_cache\\StackMiddleware\\PageCache->fetch()\n#34 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(82): Drupal\\page_cache\\StackMiddleware\\PageCache->lookup()\n#35 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\\page_cache\\StackMiddleware\\PageCache->handle()\n#36 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\\Core\\StackMiddleware\\ReverseProxyMiddleware->handle()\n#37 /data/www/*/htdocs/web/modules/contrib/detect_mobile/src/Middleware/MobileDetectMiddleware.php(61): Drupal\\Core\\StackMiddleware\\NegotiationMiddleware->handle()\n#38 /data/www/*/htdocs/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\\detect_mobile\\Middleware\\MobileDetectMiddleware->handle()\n#39 /data/www/*/htdocs/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\\StackedHttpKernel->handle()\n#40 /data/www/*/htdocs/web/index.php(19): Drupal\\Core\\DrupalKernel->handle()\n#41 {main}

DropInTheOcean’s picture

In case it helps anyone, in my case the error occurred after a scheduled server reboot.
The php8.1-fpm.service was not running - apparently it was started manually. I needed to enable (to run automatically on boot) with:
systemctl enable php8.1-fpm.service

Edit: Day later the issue returned. systemctl restart apache2 && systemctl restart php8.1-fpm.service solves the issue short term. It looks like something is crashing php8.1-fpm?

ttnt’s picture

Hello,
After updating to 9.3.3 I also got this error, I reported it in slack at the time.
[error] [pid 2894254] mod_proxy_fcgi.c(887): [client 157.193.192.109:0] AH01071: Got error 'PHP message: Error: Call to undefined function _drupal_error_handler_real() in /data/sites/web/core/lib/Drupal/Core/DrupalKernel.php on line 568 #0 /data/sites/web/core/lib/Drupal/Core/DrupalKernel.php(568): _drupal_error_handler()\n#1 /data/sites/web/core/lib/Drupal/Core/DrupalKernel.php(568): require_once()\n#2 /data/sites/web/core/lib/Drupal/Core/DrupalKernel.php(583): Drupal\\Core\\DrupalKernel->loadLegacyIncludes()\n#3 /data/sites/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(46): Drupal\\Core\\DrupalKernel->preHandle()\n#4 /data/sites/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\\Core\\StackMiddleware\\KernelPreHandle->handle()\n#5 /data/sites/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\\page_cache\\StackMiddleware\\Pag...'
The answer I got was the following:

Ambient.Impact:  2 months ago
I just searched my install of 9.3.3 on PHP 8.1.1 for _drupal_error_handler_real(), and it's core\includes\errors.inc for me. I'd guess something might have trashed that include - are you applying any patches to core via Composer that might have altered it?

Now I didn't apply patches and I just wanted to check if new composer updates worked fine, I didn't have any problems anymore and just forgot about it. Tried to bump the server to 8.1 again today and... well, here I am again :).
I hope there's a logical explanation for this, as I'll have to update to 8.1 sooner or later.

edit: it's worth noting that before my update to 9.3.3 I was running PHP8.1 just fine. I usually apply all core updates prior to every third Wednesday of the month ahead of the security window, so I'm not 100% sure if it's the patch release or the minor before that introduced it for me.

catch’s picture

Category: Support request » Bug report
Priority: Normal » Critical
Issue tags: +PHP 8.1

Bumping this to critical and moving to a bug report, this looks like a PHP 8.1 regression in the composer autoloader, but it might be triggered by some weird things in our error handling.

The important part of the stack trace for me:

_drupal_error_handler_real() (Line: 346)
_drupal_error_handler() (Line: 571)
include('[site-directory]/includes/bootstrap.inc') (Line: 571)
Composer\Autoload\includeFile() (Line: 428)
Composer\Autoload\ClassLoader->loadClass() (Line: 75)
Drupal\search_api\Backend\BackendPluginBase->logException() (Line: 642)

As with #3258987-30: Status report should warn about OPcache bug in PHP 8.1.0 to 8.1.5 restarting fpm cleared the error, so could be APC caching the wrong file location somehow? This happened to me just after updating core locally.

plessas’s picture

I also encountered the same issue in an Almalinux server, running php 8.1.4 and Drupal 9.3.8. The error appeared when the Anonymous user tried to visit a previously published page that is now unpublished. Restarting php-fpm solved the issue for now...

ConradFlashback’s picture

I confirm #33.

So I have two problems:

1) This is the error when I open a content (node/product variation) not published. But in my case my site did'nt crash completely, error goes only in log.

Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() (line 63 of /data/www/*/htdocs/web/core/includes/errors.inc)
#0 /data/www/*/htdocs/web/core/includes/bootstrap.inc(346): _drupal_error_handler_real()
#1 /data/www/*/htdocs/vendor/composer/ClassLoader.php(571): _drupal_error_handler()
#2 /data/www/*/htdocs/vendor/composer/ClassLoader.php(571): include('...')
#3 /data/www/*/htdocs/vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile()
#4 /data/www/*/htdocs/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(44): Composer\Autoload\ClassLoader->loadClass()
#5 /data/www/*/htdocs/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(97): Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->on403()
#6 [internal function]: Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onException()
#7 /data/www/*/htdocs/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func()
#8 /data/www/*/htdocs/vendor/symfony/http-kernel/HttpKernel.php(219): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()
#9 /data/www/*/htdocs/vendor/symfony/http-kernel/HttpKernel.php(91): Symfony\Component\HttpKernel\HttpKernel->handleThrowable()
#10 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
#11 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
#12 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#13 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\page_cache\StackMiddleware\PageCache->fetch()
#14 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(82): Drupal\page_cache\StackMiddleware\PageCache->lookup()
#15 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#16 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#17 /data/www/*/htdocs/web/modules/contrib/detect_mobile/src/Middleware/MobileDetectMiddleware.php(61): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#18 /data/www/*/htdocs/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\detect_mobile\Middleware\MobileDetectMiddleware->handle()
#19 /data/www/*/htdocs/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle()
#20 /data/www/*/htdocs/web/index.php(19): Drupal\Core\DrupalKernel->handle()
#21 {main}

2) This is the error when site crashes and I must restart php-fpm to temporarily resolve.

Error: Class "Drupal\\Core\\Logger\\RfcLogLevel" not found in /data/www/*/htdocs/web/core/includes/errors.inc on line 26 #0 /data/www/*/htdocs/web/core/includes/errors.inc(60): drupal_error_levels()\n#1 /data/www/*/htdocs/web/core/includes/bootstrap.inc(346): _drupal_error_handler_real()\n#2 /data/www/*/htdocs/vendor/composer/ClassLoader.php(571): _drupal_error_handler()\n#3 /data/www/*/htdocs/vendor/composer/ClassLoader.php(571): include('...')\n#4 /data/www/*/htdocs/vendor/composer/ClassLoader.php(428): Composer\\Autoload\\includeFile()\n#5 /data/www/*/htdocs/web/core/lib/Drupal/Core/Logger/LoggerChannelFactory.php(34): Composer\\Autoload\\ClassLoader->loadClass()\n#6 /data/www/*/htdocs/web/modules/contrib/metatag/src/MetatagManager.php(88): Drupal\\Core\\Logger\\LoggerChannelFactory->get()\n#7 /data/www/*/htdocs/web/core/lib/Drupal/Component/DependencyInjection/Container.php(262): Drupal\\metatag\\MetatagManager->__construct()\n#8 /data/www/*/htdocs/web/core/lib/Drupal/Component/DependencyInjection/Container.php(176): Drupal\\Component\\DependencyInjection\\Container->createService()\n#9 /data/www/*/htdocs/web/core/lib/Drupal.php(198): Drupal\\Component\\DependencyInjection\\Container->get()\n#10 /data/www/*/htdocs/web/modules/contrib/metatag/metatag.module(492): Drupal::service()\n#11 /data/www/*/htdocs/web/modules/contrib/metatag/metatag.module(298): metatag_get_tags_from_route()\n#12 /data/www/*/htdocs/web/modules/contrib/metatag/metatag.module(244): _metatag_remove_duplicate_entity_tags()\n#13 /data/www/*/htdocs/web/core/lib/Drupal/Core/Extension/ModuleHandler.php(539): metatag_entity_view_alter()\n#14 /data/www/*/htdocs/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(305): Drupal\\Core\\Extension\\ModuleHandler->alter()\n#15 /data/www/*/htdocs/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(239): Drupal\\Core\\Entity\\EntityViewBuilder->buildMultiple()\n#16 [internal function]: Drupal\\Core\\Entity\\EntityViewBuilder->build()\n#17 /data/www/*/htdocs/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(101): call_user_func_array()\n#18 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(772): Drupal\\Core\\Render\\Renderer->doTrustedCallback()\n#19 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(363): Drupal\\Core\\Render\\Renderer->doCallback()\n#20 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(201): Drupal\\Core\\Render\\Renderer->doRender()\n#21 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(241): Drupal\\Core\\Render\\Renderer->render()\n#22 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/Renderer.php(564): Drupal\\Core\\Render\\MainContent\\HtmlRenderer->Drupal\\Core\\Render\\MainContent\\{closure}()\n#23 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(242): Drupal\\Core\\Render\\Renderer->executeInRenderContext()\n#24 /data/www/*/htdocs/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(132): Drupal\\Core\\Render\\MainContent\\HtmlRenderer->prepare()\n#25 /data/www/*/htdocs/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\\Core\\Render\\MainContent\\HtmlRenderer->renderResponse()\n#26 [internal function]: Drupal\\Core\\EventSubscriber\\MainContentViewSubscriber->onViewRenderArray()\n#27 /data/www/*/htdocs/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func()\n#28 /data/www/*/htdocs/vendor/symfony/http-kernel/HttpKernel.php(163): Drupal\\Component\\EventDispatcher\\ContainerAwareEventDispatcher->dispatch()\n#29 /data/www/*/htdocs/vendor/symfony/http-kernel/HttpKernel.php(80): Symfony\\Component\\HttpKernel\\HttpKernel->handleRaw()\n#30 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\\Component\\HttpKernel\\HttpKernel->handle()\n#31 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\\Core\\StackMiddleware\\Session->handle()\n#32 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\\Core\\StackMiddleware\\KernelPreHandle->handle()\n#33 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\\page_cache\\StackMiddleware\\PageCache->fetch()\n#34 /data/www/*/htdocs/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(82): Drupal\\page_cache\\StackMiddleware\\PageCache->lookup()\n#35 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\\page_cache\\StackMiddleware\\PageCache->handle()\n#36 /data/www/*/htdocs/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\\Core\\StackMiddleware\\ReverseProxyMiddleware->handle()\n#37 /data/www/*/htdocs/web/modules/contrib/detect_mobile/src/Middleware/MobileDetectMiddleware.php(61): Drupal\\Core\\StackMiddleware\\NegotiationMiddleware->handle()\n#38 /data/www/*/htdocs/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\\detect_mobile\\Middleware\\MobileDetectMiddleware->handle()\n#39 /data/www/*/htdocs/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\\StackedHttpKernel->handle()\n#40 /data/www/*/htdocs/web/index.php(19): Drupal\\Core\\DrupalKernel->handle()\n#41 {main}

propercroc’s picture

Running Ubuntu-Plesk with PHP 8.1 and got error from #4 .

In Plesk, I tried both "FPM Application served by Apache" and "dedicated FPM Application served by Apache". Both show this error, but only after some time. Sometimes hours, sometimes days. Restarting fixes the error, but re-appears after a while.

Only appears to logged-in-users, anonymous is not exposed to this error. All /admin/* pages are concerned.

I just downgraded eight Drupal9 instances to php7.4 because of this.

Good luck finding this one and thanks for everybodies help on this.

mrweiner’s picture

@ProperCroc, it sounds like you can probably run php8.0 instead of 7.4 without issue. The problem seems to have to do with 8.1 specifically.

ConradFlashback’s picture

Me too I downgraded php version for my project. So I can't test now.
But I will follow this issue.

plessas’s picture

In my case the error reappeared after around 10 days, again when visiting pages without appropriate access permissions. Restarting php-fpm results in the normal 403 access denied page.

francoud’s picture

Same problem here. Website version: Drupal 9.3.9. Normally running with PHP 7.4 with no problem. Using PHP 8.1 I have this error:

Error: Call to undefined function _drupal_error_handler_real() in require_once() (line 568 of /var/www/clients/client2/web52/web/core/lib/Drupal/Core/DrupalKernel.php)
#0 /var/www/clients/client2/web52/web/core/lib/Drupal/Core/DrupalKernel.php(568): _drupal_error_handler()
#1 /var/www/clients/client2/web52/web/core/lib/Drupal/Core/DrupalKernel.php(568): require_once()
#2 /var/www/clients/client2/web52/web/core/lib/Drupal/Core/DrupalKernel.php(583): Drupal\Core\DrupalKernel->loadLegacyIncludes()
#3 /var/www/clients/client2/web52/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(46): Drupal\Core\DrupalKernel->preHandle()
#4 /var/www/clients/client2/web52/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(191): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#5 /var/www/clients/client2/web52/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(128): Drupal\page_cache\StackMiddleware\PageCache->fetch()
#6 /var/www/clients/client2/web52/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(82): Drupal\page_cache\StackMiddleware\PageCache->lookup()
#7 /var/www/clients/client2/web52/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#8 /var/www/clients/client2/web52/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#9 /var/www/clients/client2/web52/web/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#10 /var/www/clients/client2/web52/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle()
#11 /var/www/clients/client2/web52/web/index.php(19): Drupal\Core\DrupalKernel->handle()
#12 {main}

both in watchdog and on server log (apache on debian). Note that the website was created from tarbal, not with composer.

Another website - same server - but created with composer, works perfectly with PHP 8.1.

parijke’s picture

Same problem here with Drupal 9.3.9. Reverted back to php 8.0.17

lingros’s picture

We have same problem with Drupal 9.3.9 on PHP-FPM 8.1.4. After disabling OPcache the issue is gone, but I hope it's not final solution. Website previously ran on PHP-FPM 7.4 without problem.

rafageist’s picture

The original error is another. For example, in PHP 8.1, by default, deprecated notice is a fatal error:

Return type of Drupal\google_analytics\Component\Render\GoogleAnalyticsJavaScriptSnippet::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice.

The problem is that when Drupal tries to call the error handler, it doesn't exist before the error occurs.

The solution?

1. The Drupal team needs to fix the error's handler loading sequence.
2. Module developers should check for compatibility with PHP 8.1
3. Fow now, change the code of this function on bootstrap.inc:

function _drupal_error_handler($error_level, $message, $filename = NULL, $line = NULL) {
  require_once __DIR__ . '/errors.inc';

  if (!function_exists('_drupal_error_handler_real')) {
    var_dump([$error_level, $message, $filename, $line]);
    die();
  }

  return _drupal_error_handler_real($error_level, $message, $filename, $line);
}

The line with include, no fix the problem, but show the real error: PHP 8.1 Incompatibility

mfb’s picture

I haven't reproduced this issue myself yet, but I did notice that some potentially-related issues re: Opcache on PHP 8.1 have been reported, e.g. https://github.com/php/php-src/issues/8164 and https://github.com/php/php-src/issues/8063

rafageist’s picture

Adding temporarily opcache_reset() in the index.php and adding #[\ReturnTypeWillChange] to suppress compatibility errors solved my problem.

mfb’s picture

re: #44 it looks like Opcache bug fix is in progress, could be verified by building PHP from source or trying 8.1.6 when it's released

john_b’s picture

I have seen this on php 8.1.4, which crashed the site for anonymous only. Upgrading the Debian package to 8.1.5 appears to have fixed it, at least in the short term.

catch’s picture

Found an old issue which is similar #1948600: PHP Fatal error: Class 'Insert' not found in \SomeNamespace\SomeClass.php on $lastline and might point to the underlying issue - is it because an error is triggered in the process of loading the class itself? Should we require_once the error class somewhere?

szato’s picture

Confirmed: We got this error on 8.1.2, updating php to 8.1.5 fixed.

xjm’s picture

Title: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() » PHP 8.1.2-8.1.4 issue: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real()
Issue tags: +Needs release manager review, +beta blocker
Parent issue: » #3118149: [meta] Requirements for tagging Drupal 10.0.0-beta1

If PHP 8.1.5 does indeed resolve the issue, we might want to increase Drupal 10's minimum requirement to 8.1.5.

For Drupal 9. we could also add a platform-level constraint forbidding PHP 8.1.2-8.1.4 if that is confirmed to be the root of the problem.

mfb’s picture

That would be great although I'm not clear why 8.1.5 would resolve this, as the issue(s) I mentioned in #44 will be fixed in 8.1.6

Restarting PHP temporarily resolves the opcache problem so false negatives are possible..

catch’s picture

Title: PHP 8.1.2-8.1.4 issue: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() » Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real()
Issue summary: View changes

Have tried to update the issue summary with a few more details.

I'm leaving the 'Needs steps to reproduce' tag on because it would be amazing to have clear steps to reproduce. However this is not the same as 'cannot reproduce' in this case. I've personally experienced the error developing locally, only on one install, at a frequency of about once every ten days, so it is both intermittent and extremely infrequent.

When I tried to debug, I couldn't find any obvious place where Drupal or Composer autoloader code was at fault (apart from the PHP 8.1 deprecation notice that triggers the bug in the first place). It seemed like it was getting to composer requiring Error.php successfully, but then PHP not actually getting the Error class into memory and fatalling since the autoloader thought it had autoloaded by that point, which to me points to a PHP bug.

It has been extremely rare for PHP to issue deprecation notices when classes are autoloaded prior to PHP 8.1, so it might be that there's a pre-existing (PHP or Drupal or Composer) bug when the autoloader triggers the error handler, in turn triggering the autoloader, #1948600: PHP Fatal error: Class 'Insert' not found in \SomeNamespace\SomeClass.php on $lastline suggests that something similar may have happened before, and there just hasn't been enough cases for us to run into it. Or it could be that there's a new bug in PHP 8.1 combined with the new deprecation errors.

Feels like there is a possible workaround where we could require Error.php from the error handler before the class is autoloaded and shortcut the autoloader, but it will be very hard to verify this solves the problem because you could potentially still have the bug and go weeks without running into it. And it will also be hard to verify when it's safe to remove, because it's such an infrequent intermittent error.

Also removing PHP versions from the issue summary because until we have a specific PHP commit to, not sure I want to assume it's fixed by PHP 8.1.5 - or at least not until people have gone a month or two without experiencing it again.

mfb’s picture

PHP 8.1.6RC1 is available if anyone wants to work on verifying the potential fix in https://github.com/php/php-src/pull/8297 (which as @catch said could take a while)

xjm’s picture

At least two people say specitically say updating to PHP 8.1.5 resolved the issue. What additional proof would we like?

catch’s picture

@xjm I think we need someone to go a full month or more, with the same PHP 8.1 deprecation error that triggered the bug left unfixed, and triggered on the environment often enough, without also running into the fatal error.

Just not having the error for a couple of days after upgrading could equally happen if it's still there, since it's so infrequent.

parijke’s picture

Can confirm 8.1.5 keeps stable untill now.

petr illek’s picture

@catch I just got this error on 9.3.12 running on PHP 8.1.4. The steps to trigger it every time is creating new user with the Email notification checkbox checked.

Error: Class "Drupal\Core\Utility\Error" not found ve funkci _drupal_error_handler_real() (řádek 63 souboru /home/atecheb/public_html/web/core/includes/errors.inc)

#0 /home/atecheb/public_html/web/core/includes/bootstrap.inc(346): _drupal_error_handler_real()
#1 /home/atecheb/public_html/vendor/composer/ClassLoader.php(571): _drupal_error_handler()
#2 /home/atecheb/public_html/vendor/composer/ClassLoader.php(571): include('...')
#3 /home/atecheb/public_html/vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile()
#4 /home/atecheb/public_html/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(69): Composer\Autoload\ClassLoader->loadClass()
#5 /home/atecheb/public_html/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(97): Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onError()
#6 [internal function]: Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onException()
#7 /home/atecheb/public_html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func()
#8 /home/atecheb/public_html/vendor/symfony/http-kernel/HttpKernel.php(219): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()
#9 /home/atecheb/public_html/vendor/symfony/http-kernel/HttpKernel.php(91): Symfony\Component\HttpKernel\HttpKernel->handleThrowable()
#10 /home/atecheb/public_html/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
#11 /home/atecheb/public_html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
#12 /home/atecheb/public_html/web/modules/contrib/shield/src/ShieldMiddleware.php(265): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#13 /home/atecheb/public_html/web/modules/contrib/shield/src/ShieldMiddleware.php(221): Drupal\shield\ShieldMiddleware->bypass()
#14 /home/atecheb/public_html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\shield\ShieldMiddleware->handle()
#15 /home/atecheb/public_html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#16 /home/atecheb/public_html/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#17 /home/atecheb/public_html/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle()
#18 /home/atecheb/public_html/web/index.php(19): Drupal\Core\DrupalKernel->handle()
#19 {main}
berdir’s picture

Did also run into this one in a project. Did suddenly happen ~10h after a deployment. Agreed looks like a very weird classloading problem.

Another slightly different stacktrace:

Error: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() (Zeile 63 in /app/web/core/includes/errors.inc)

#0 /app/web/core/includes/bootstrap.inc(346): _drupal_error_handler_real(8192, 'Return type of ...', '/app/web/module...', 39)
#1 /app/vendor/composer/ClassLoader.php(571): _drupal_error_handler(8192, 'Return type of ...', '/app/web/module...', 39)
#2 /app/vendor/composer/ClassLoader.php(571): include('/app/web/core/i...')
#3 /app/vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile('/app/vendor/com...')
#4 /app/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(44): Composer\Autoload\ClassLoader->loadClass('Drupal\\Core\\Uti...')
#5 /app/web/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(121): Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->on403(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent))

This is on an access denied page in this specific case. Unfortunately shortened strings. What's super weird to me is that autoloading the error class actually ends up loading an includes file and then it jumps into the drupal error handler with something that I think comes from a module? Also google_analytics I think.

But it also happened very early in bootstrap then suddenly:

Error: Call to undefined function _drupal_error_handler_real() in require_once() (Zeile 568 in /app/web/core/lib/Drupal/Core/DrupalKernel.php)

#0 /app/web/core/lib/Drupal/Core/DrupalKernel.php(568): _drupal_error_handler(8192, 'Return type of ...', '/app/web/module...', 39)
#1 /app/web/core/lib/Drupal/Core/DrupalKernel.php(568): require_once()
#2 /app/web/core/lib/Drupal/Core/DrupalKernel.php(583): Drupal\Core\DrupalKernel->loadLegacyIncludes()
#3 /app/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(46): Drupal\Core\DrupalKernel->preHandle(Object(Symfony\Component\HttpFoundation\Request))
berdir’s picture

Another indication that this is a bug in the opcache is that the problem didn't appear on CLI, cron jobs as well as a full drush cr worked just fine.

Possible PHP issue: https://github.com/php/php-src/issues/8164

=> This should be fixed with PHP 8.1.6.

catch’s picture

https://github.com/php/php-src/issues/8164 looks extremely likely, reports are very similar to the ones here, that'd be enough for me to want to raise the 10.0.x minimum PHP version to 8.1.6, and we can document why somewhere.

We probably also need to do something for 9.4.x, like try to stop people running on 8.1.0-8.1.5, but that might need a special hook_requirements() rather than using the existing constants?

berdir’s picture

Oh, I think i misread that comment. Looks like 8.1.6 isn't actually released yet? Only 8.1.6RC is, per that comment in that issue.

FWIW, I checked in with platform.sh, their containers are currently on 8.1.4 and depend on https://tracker.debian.org/pkg/php8.1, which currently is only on 8.1.5 ( I have been informed that this is wrong, they do not depend on that), I guess quite a few docker/container based solutions depend on that in one way or another? ddev containers are on 8.1.3 for me.

No idea about our DrupalCI images and how quickly they'll update to 8.1.6 once it is actually released.

Requiring 8.1.6 too early might be quite annoying for developing/testing d10. Maybe start with a requirements warning or so, that's also something that could be backported to D9?

catch’s picture

Maybe start with a requirements warning or so, that's also something that could be backported to D9?

Yep we need this for 9.x/10.x anyway and can open a separate issue for making it a harder requirement in 10.x - definitely might want to wait a couple of months for 8.1.6 to be more widely available, or limit it to a recommendation even.

mfb’s picture

PHP 8.1.6 is out, which resolves the upstream issues mentioned in #44 which 🤞 is the same as this issue

I don't think there needs to be a hard dependency on a particular PHP version since there seem to be workarounds for older versions of 8.1 (fix code that logs errors/deprecations or disable opcache) - but adding a recommendation/warning could be helpful.

cilefen’s picture

@mfb I agree with you.

catch’s picture

Status: Active » Needs review
StatusFileSize
new482 bytes

Maybe we can do this for 10.0.x, but I'm not sure if it's slightly mis-using the RECOMMENDED_PHP constant.

Another option would be a hook_requirements() for all supported Drupal versions that adds a warning for PHP >= 8.1.0 && < 8.1.6.

Yet another option is to document this on Drupal.org under PHP requirements somewhere and not bother putting a warning in core at all.

cilefen’s picture

I am in favor of the hook_requirements way.

catch’s picture

Issue summary: View changes
Status: Needs review » Needs work
Issue tags: -Needs steps to reproduce, -Needs release manager review

OK I've updated the issue summary a bit and add the hook_requirements() suggestion to the proposed resolution there.

catch’s picture

Title: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() » Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() due to bug in PHP 8.1.0-8.1.5
Priority: Critical » Major

Also going to bump this down to major since it's not really a core bug. However it would be good to add the hook_requirements() since this is a very tricky one to diagnose.

catch’s picture

Category: Bug report » Task
Issue tags: -beta blocker

Also a task now. And removing the beta blocker tag.

ravi.shankar’s picture

StatusFileSize
new482 bytes

Added reroll of patch #65 on Drupal 9.3.x.

mrweiner’s picture

Status: Needs work » Needs review

Opened an MR that adds a system_requirements(). Reading through the comments on https://www.php.net/manual/en/function.version-compare.php, there may be some edge cases we'll miss but I think it'll catch most scenarios.

mrweiner’s picture

I'm unsure whether we also need the RECOMMENDED_PHP bit from #65 and #70.

cilefen’s picture

There is system_requirements implementation in system.install.

cilefen’s picture

Status: Needs review » Needs work
catch’s picture

@mrweiner I think we're better off without RECOMMENDED_PHP if we go the system_requirements() route, at least for this issue.

mrweiner’s picture

Status: Needs work » Needs review

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

xjm’s picture

Issue tags: +Drupal 10 beta should-have

Hiding patch files so that it's clear where the current work is.

xjm’s picture

Went to rebase the branch but it's un-rebaseable, so opening a new MR against 9.4.x is easier given the small scope.

A few issues:

diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index f07133bcd4..ddbe2be63b 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -46,6 +46,17 @@ function system_requirements($phase) {
       'weight' => -10,
     ];
 
+    $php_version = phpversion();
+    if(version_compare($php_version, '8.1.0', '>=')
+      && version_compare($php_version, '8.1.6', '<')) {
+      $requirements['error_prone_php_version_in_use'] = [
+        'title' => t('Error-prone php version in use'),
+        'value' => $php_version,
+        'description' => t('Error-prone PHP version in use: %php_version. PHP versions >= 8.1.0 and < 8.1.6 are known to cause intermittent runtime errors. It is recommended to either upgrade to >= 8.1.6 or downgrade to < 8.1.0.', ['%php_version' => $php_version]),
+        'severity' => REQUIREMENT_WARNING,
+      ];
+    }
+
     // Display the currently active installation profile, if the site
     // is not running the default installation profile.
     $profile = \Drupal::installProfile();
  1. The if doesn't follow our coding standards.
  2. I don't think we should tell people to downgrade their PHP version.
  3. "Error-prone" is alarmingly vague and a bit sweeping.

xjm’s picture

Made some edits to help address #81.

I do think we should also increase RECOMMENDED_PHP to 8.1.6. It's already 8.1 on all actively developed branches.

catch’s picture

I've opened #3294938: Increase RECOMMENDED_PHP to 8.1.6 which I think we should definitely do in 10.0.x and maybe in 9.5.x

For 9.4.x IMO the new system_requirements() is better for backporting to a patch release, since it may not be straightforward for everyone to get onto 8.1.6 given it's only been out for six weeks.

xjm’s picture

Issue tags: +Needs usability review
xjm’s picture

I realized we should consolidate this message into the existing messaging logic about PHP versions, because it's bad UX for the user to have two different, possibly conflicting messages about their PHP version.

However, this also underscores why I think we should backport a change in RECOMMENDED_PHP to 9.4.x. Either that, or we lower it back to 8.0 on 9.4. Because if the user sees a message telling them to upgrade to at least 8.1, then upgrades to 8.1.3 or whatever, then sees another message telling them to upgrade to 8.1.6... speaking for myself, I'd want to stab things at that point.

catch’s picture

PHP 8.0 is security supported for longer than 9.4 will be, so lowering it there doesn't seem too bad. We could still have the hook_requirements() for people on 8.1.0-8.1.5 in that case.

xjm’s picture

Issue summary: View changes
StatusFileSize
new56.43 KB

Current logic displays:

  1. "Too old" message on PHP less than 7.4
  2. This message on PHP 8.1.0-8.1.5
  3. Recommended PHP info message on PHP 7.4 or 8.0.
catch’s picture

#3294938: Increase RECOMMENDED_PHP to 8.1.6 is in for 10.1.x-9.5.x, and I opened #3295085: [9.4 ONLY] Lower RECOMMENDED_PHP to 8.0 for 9.4.x

Patch looks good to me here.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

The message is helpful to identify bug

xjm’s picture

For #89, I think it's an "and". We should both lower the recommended PHP, and backport an amended version of this that recommends updating to either PHP 8.0.0+ or PHP 8.1.6+ for 9.4.x only. It's worth having messaging that is correct since the branch has another year of coverage remaining.

xjm’s picture

So I think we should do #3295085: [9.4 ONLY] Lower RECOMMENDED_PHP to 8.0, and then the 9.4.x backport of this should adjust the message you get on PHP 7.4 and lower to indicate PHP 8.0+ or 8.1.6+ are recommended. I wonder if we can also do that without breaking strings...

xjm’s picture

I pushed a new MR for 9.4.x. It displays the warning by itself when PHP 8.1.0-8.1.5 is installed, and also adds a note about it when recommending the user update their PHP version. I wrote the text in such a way that it should make sense regardless of whether PHP 8.0 or 8.1 is being recommended.

It's a bit ugly, but it does avoid breaking existing translatable strings in a patch release, and the use of FormattableMarkup won't be there in 9.5 and above.

xjm’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs review
StatusFileSize
new119.08 KB
new126.06 KB
new24.55 KB
new69.6 KB

Screenshots of the 9.4.x MR:

On PHP 7.4, with HEAD

On PHP 8.0, with HEAD

On PHP 8.0, with #3295085: [9.4 ONLY] Lower RECOMMENDED_PHP to 8.0

On PHP 8.1

Setting back to NR for the 9.4.x MR and for the UX review of both that and the 9.5.x+ version in the IS.

benjifisher’s picture

Status: Needs review » Needs work
Issue tags: -Needs usability review

Usability review

We discussed this issue at #3296084: Drupal Usability Meeting 2022-07-15. That issue will have a link to a recording of the meeting.

For the record, the attendees at the usability meeting were @rkoller, @shaal, @simohell, @worldlinemine, and me.

I see that #3295085: [9.4 ONLY] Lower RECOMMENDED_PHP to 8.0 has been fixed since the last comment on this issue, so I tested myself with 9.4.x, 9.5.x, and the feature branches for this issue.

I notice that the PHP version information is always in the "General System Information" at the top of the page and sometimes in the "Status Details" section. I am not sure exactly when the version information is shown in the latter section, but this issue does not change that, does it?

Here is what I see in the various cases, hacking core/modules/system/system.install to change the PHP version:


9.4.x

  • PHP 8.0:

    8.0.2 (more information)

  • PHP 8.1.2:

    8.1.2 (more information)

  • PHP 8.1.6:

    8.1.6 (more information)

3258987-9.4.x

  • PHP 8.0:

    8.0.2 (more information)

  • PHP 8.1.2: (warning)

    8.1.2 (more information)
    Note that PHP 8.1 versions before 8.1.6 have a bug with the PHP OPcache that can cause intermittent, fatal runtime errors with class autoloading. It is recommended to upgrade to at least PHP 8.1.6 when using PHP 8.1.

  • PHP 8.1.6:

    8.1.6 (more information)

3258987-warning

  • PHP 8.0:

    8.0.2 (more information)
    It is recommended to upgrade to PHP version 8.1 or higher for the best ongoing support. See PHP’s version support documentation and the Drupal PHP requirements page for more information.

  • PHP 8.1.2: (warning)

    8.1.2 (more information)
    PHP 8.1 versions before 8.1.6 have a bug with the PHP OPcache that can cause intermittent, fatal runtime errors with class autoloading. It is recommended to upgrade to at least PHP 8.1.6.

  • PHP 8.1.6:

    8.1.6 (more information)

9.5.x

  • PHP 8.0:

    8.0.2 (more information)
    It is recommended to upgrade to PHP version 8.1.6 or higher for the best ongoing support. See PHP’s version support documentation and the Drupal PHP requirements page for more information.

  • PHP 8.1.2:

    8.1.2 (more information)
    It is recommended to upgrade to PHP version 8.1.6 or higher for the best ongoing support. See PHP’s version support documentation and the Drupal PHP requirements page for more information.

  • PHP 8.1.6:

    8.1.6 (more information)


I notice that the message in the 3258987-warning branch is a little shorter than the one in the 3258987-9.4.x branch: the latter starts with "Note that" and ends with "when using PHP 8.1". This is a case where "less is more". In fact, "Note that" is one of my pet peeves.

  1. Do not use "Note that".
  2. If you think that "… when using PHP 8.1" is needed because 8.0 is still an option, then consider other ways to phrase it. For example:
    • It is recommended to avoid PHP 8.1.0 to 8.1.5.
    • It is recommended to upgrade to at least PHP 8.1.6 or to downgrade to PHP 8.0.
    • When using PHP 8.1, it is recommended to upgrade to at least PHP 8.1.6.
  3. For PHP 8.0, the 9.5.x branch refers to "8.1.6". If there is going to be a recommendation for 9.4.x, as in the 3258987-warning branch, then it should also use "8.1.6" instead of just "8.1".
  4. Suggestion: consider changing "PHP 8.1 versions" to "Versions of PHP 8.1".
kraut’s picture

Late to the party but working with Canonical to land the fix in Ubuntu 22.04 LTS.
Inside the Ubuntu community this requires an StableReleaseUpdate to get fixed.
Means it's not as simple as merging current 8.1.7 from Debian unstable aka sid.

Hence we went down the road like with CVEs and backported the actual patch.
From the 8.1.6 release we pinned it down to this PR on the OPcache bug cited:
https://github.com/php/php-src/pull/8297

We could use some Drupal community help as we miss a direct bug reproducer :)
Got you a PPA for testing and packages that get superseded after the SRU passed:
https://launchpad.net/~kraut.hosting/+archive/ubuntu/php

Love to get feedback here and at best a bug reproducer or contributing factors :)
FYI https://bugs.launchpad.net/ubuntu/+source/php8.1/+bug/1983205

mfb’s picture

That upstream PR includes a test / minimal reproduce case. With opcache enabled, it loads a class that triggers a compile-time error, then checks that additional classes can still be correctly autoloaded during shutdown.

phenaproxima’s picture

I wonder if we cannot simplify this a tad. My thoughts:

There are two conditions that need to be true for this bug to manifest: you have to be on PHP 8.1.0 through 8.1.5, and opcache has to be enabled. So let's only show this warning if those are both true.

Secondly, the error should be more consistent. What if we said something like:

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

A number of words are removed here, like "intermittent" and "runtime". (We don't have to mention the PHP version range which has the bug, IMHO; that merely adds cognitive load, when I think the only message we should be delivering is "you have a problem right now; do this thing to fix it".)

And again, we would only show this warning if those two conditions I mentioned before are true.

phenaproxima’s picture

Version: 9.4.x-dev » 10.0.x-dev
Assigned: Unassigned » phenaproxima

Assigning this to myself after discussion with @xjm.

xjm’s picture

Also, the above branch metadata change is both deliberate and temporary. More soon. :)

benjifisher’s picture

      // @todo Remove this when \Drupal::MINIMUM_PHP is at least 8.1.6.

Can we add a follow-up issue now and reference it in both code comments?

I do not see anything in the current MR that checks whether opcache is enabled, but I am not sure that such a check is a good idea. First, it is more complicated than just checking the PHP version. Second, enabling/disabling opcache is easier than upgrading PHP. Imagine the poor site owner who upgrades the system software, checks the status report ... oops, I forgot to enable opcache ... and then does not re-check the status report.

I like your wording, and I agree that it is not worth delaying this issue too much while debating it. On the other hand, I would like to see the current wording in the issue summary (Proposed resolution section and User interface changes section), so I am adding the tag for an IS update.

phenaproxima’s picture

Issue summary: View changes

I do not see anything in the current MR that checks whether opcache is enabled, but I am not sure that such a check is a good idea. First, it is more complicated than just checking the PHP version.

Yeah, I thought about this. I'm not sure if the bug only manifests itself if the opcache extension is enabled, but if so, we should probably hide this check behind a extension_loaded('opcache') check or similar, since I agree that we should offer people the solution that is most closely within reach (disabling opcache).

xjm’s picture

Posted some feedback on the 10.0 MR that also will apply to the 9.5 MR.

phenaproxima’s picture

Untagging for an issue summary update, 'cause I did it.

phenaproxima’s picture

A suggestion for what to do in Drupal 9.4:

If Drupal is running on PHP lower than 8.1, then we should tell them (at REQUIREMENT_INFO severity) to upgrade to PHP 8.1.6 or later. Let's just hard-code that value. I'm not sure we need to append anything. If they ignore our advice and upgrade to 8.1.0 through 8.1.5, they'll get the same warning that we show people on Drupal 9.5 and 10.0.

Thoughts?

phenaproxima’s picture

Issue summary: View changes
StatusFileSize
new16.22 KB
new32.37 KB
new51.48 KB
new56.63 KB
new39.57 KB

Let's get some screenshots up in here.

This is what happens when you use different PHP versions against the existing 9.4.x MR. (As @benjifisher did, I hacked system.install to change the detected PHP version).

PHP 8.1.9 doesn't have any complaints, as you'd expect:

The 9.4.x MR against PHP 8.1.9

PHP 8.0.3, 7.4.2, and 7.3.1 all passively warn that danger lies ahead:

The 9.4.x MR against PHP 8.0.3
The 9.4.x MR against PHP 7.4.2
The 9.4.x MR against PHP 7.3.1

And PHP 8.1.1 shows the stern warning we'd want:

The 9.4.x MR against PHP 8.1.1

phenaproxima’s picture

Issue summary: View changes
StatusFileSize
new34.41 KB
new97.39 KB
new87.78 KB
new87.01 KB
new101.4 KB

Here are screenshots for the 9.5.x MR. This is straightforward.

On PHP 8.1.9, there are no complaints, as you'd expect:

The 9.5.x MR on PHP 8.1.9

On PHP 8.1.1, it complains:

The 9.5.x MR on PHP 8.1.1

And on all other versions, it doesn't complain, but recommends you go to 8.1.6 (a.k.a., \Drupal::RECOMMENDED_PHP):

The 9.5.x MR on PHP 8.0.3
The 9.5.x MR on PHP 7.4.2
The 9.5.x MR on PHP 7.3.1

phenaproxima’s picture

StatusFileSize
new16.23 KB
new50.03 KB

And finally, 10.0.x is even more straightforward, since it requires PHP 8.1.0 at a minimum to even boot up.

Here's what happens with PHP 8.1.9 (spoiler: nothing):

The 10.0.x MR with PHP 8.1.9

And it gets mad with PHP 8.1.1:

The 10.0.x MR with PHP 8.1.1

xjm’s picture

Looks like the 10.0.x string has the docs links repeated twice in the last screenshot?

Other than that, this all makes sense. Once the above is fixed I think it's ready for UX review again.

phenaproxima’s picture

Issue tags: +Needs usability review

Thanks @xjm. Re-tagging for usability review.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Title: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() due to bug in PHP 8.1.0-8.1.5 » Status report should warn about OPcache bug in PHP 8.1.0 to 8.1.5

Re-titling for accuracy.

rkoller’s picture

I've queued the issue for review at #3304790: Drupal Usability Meeting 2022-08-26 or a future meeting.

phenaproxima’s picture

Status: Needs work » Needs review

Assuming tests pass, I think this is ready for code review.

benjifisher’s picture

Status: Needs review » Needs work
Issue tags: -Needs usability review

This observation is out of scope for this issue, but I want to write it down while I am thinking about it. In the "General System Information" section of the status report, there are two links with the text "more information": one under "Last Cron Run" and one under "PHP".

Thanks for adding #3305726: When Drupal::MINIMUM_PHP is 8.1.6 or greater, don't warn about OPcache bug in 8.1.0 through 8.1.5. Maybe we should add a code comment referring to that issue, similar to the comment I quoted in #104.

I see that PHP requirements already has a link to the change record for this issue. Maybe we should add a link on that page to the PHP docs.

My main usability feedback is that "less is more": do we need a link to PHP’s version support documentation? The message will be shorter if we remove that. I see that @xjm commented on the MR,

We are losing the links to the PHP version documentation from the other strings here. We should still include those.

That makes sense if a site is running on PHP 7 and we want to alert the site owner that it will not be supported much longer. Currently, the link is not helpful for a site running on PHP 8.1.2, but I guess that will change: when 8.0 is close to EOL, the site owner should really upgrade to 8.1.6+ and not downgrade to 8.0.

I think the current text is unambiguous and actionable, and I am glad that we have removed "Note that". I am removing the tag for a usability review. But the current MR for 9.4.x (the only one I have tested today) needs some work. The latest update reverts accidental changes to default.settings.php, but it makes new accidental changes to composer.*.

phenaproxima’s picture

The latest update reverts accidental changes to default.settings.php, but it makes new accidental changes to composer.*.

I swear, if I look at the merge request, I am not seeing this. Would you (or someone) be able to revert those changes?

mfb’s picture

How is a scenario such as #97 dealt with, if ubuntu LTS were to backport the fix to its php package? The version would be reported as "8.1.2" but it would in fact have various patches applied (security fixes, and apparently bug fixes too).

xjm’s picture

That makes sense if a site is running on PHP 7 and we want to alert the site owner that it will not be supported much longer. Currently, the link is not helpful for a site running on PHP 8.1.2, but I guess that will change: when 8.0 is close to EOL, the site owner should really upgrade to 8.1.6+ and not downgrade to 8.0.

Yep. It's also important because it explains what "recommended" means and caveats with it. The links should always be included if you're on less-than-recommended PHP.

benjifisher’s picture

Status: Needs work » Needs review

@phenaproxima: You are right. It was the previous branch that made those changes, not the current one. Back to NR.

@mfb: I think that is out of scope for this issue. If it actually happens, and we can extract the patch information or the Debian/Ubuntu package version from phpinfo(), then we can have a follow-up issue to update the check. Even then, I am not sure that it will be worth the added complexity.

mfb’s picture

I couldn't see how to "extract the patch information or the Debian/Ubuntu package version" - it doesn't seem like their php package makes this available, although you would think that it should, e.g. via the "extra" version info. The PHP_VERSION is 8.1.2 and PHP_EXTRA_VERSION is empty string. Anyways, yes they haven't patched it yet so *shrug*

xjm’s picture

How is a scenario such as #97 dealt with, if ubuntu LTS were to backport the fix to its php package? The version would be reported as "8.1.2" but it would in fact have various patches applied (security fixes, and apparently bug fixes too).

We can't really handle that case in core as there's no clean API to detect if the bug is fixed or not (plus I am not sure it'd be worth doing). We could add to the CR though if that happens, which is linked to the handbook page.

mullzk’s picture

- @kraut in #97:

We could use some Drupal community help as we miss a direct bug reproducer :)
Got you a PPA for testing and packages that get superseded after the SRU passed: [...]
Love to get feedback here and at best a bug reproducer or contributing factors :)
FYI https://bugs.launchpad.net/ubuntu/+source/php8.1/+bug/1983205

- We are on Ubuntu 22.04 and therefor on PHP 8.1.2.
- We experience the bug and can reproduce it on at least two of our Installations of Drupal 9.4.5.
On our site, the impact is quite heavy: Every time, Drupal wants to show an Error (e.g. Error 403
if an unauthorized user accesses the URL /admin), PHP crashes on its autoloader and Drupal produces
an ugly Error 500 instead of the correctly designed Error403-Page.
- Your fix works for us. We installed the PPA and the aformentioned bug does not occur anymore.
Unfortunately a complete Drupal Installation is probably not a very useful bug reproducer to share.

phenaproxima’s picture

Assigned: phenaproxima » Unassigned

I think all feedback is addressed here. Unassigning from myself for code review.

gambry’s picture

Status: Needs review » Reviewed & tested by the community

I reviewed the code, spending a good time to understand all the elseifs weirdnesses. But all makes sense at the end.

The only thing that got me was the nested string as placeholder in 9.4 MR, trying to understand if there were combinations where an empty paragraph could be created. Couldn't fine any, so I think this is good.

I know Bjorn was going to try and spend time tonight reviewing this. Feel free to wait for him.

Thanks all!

  • lauriii committed 0d091ad on 10.1.x
    Issue #3258987 by phenaproxima, xjm, mrweiner, catch, cilefen, mfb,...

  • lauriii committed 4c51ac5 on 10.0.x
    Issue #3258987 by phenaproxima, xjm, mrweiner, catch, cilefen, mfb,...

  • lauriii committed 5ab3f8b on 9.5.x
    Issue #3258987 by phenaproxima, xjm, mrweiner, catch, cilefen, mfb,...

lauriii’s picture

Version: 10.0.x-dev » 9.4.x-dev
Status: Reviewed & tested by the community » Fixed

Tested all branches manually and confirmed that the messages made sense in context to the minimum and recommended PHP versions for those branches.

Committed #2649 to 0d091ad and pushed to 10.1.x and cherry-picked to 10.0.x. Committed #2656 to 5ab3f8b and pushed to 9.5.x. Committed #2495 to f20c0a2 and pushed to 9.4.x. Thanks!

  • lauriii committed f20c0a2 on 9.4.x
    Issue #3258987 by phenaproxima, xjm, mrweiner, catch, cilefen, mfb,...
kraut’s picture

Version: 9.4.x-dev » 10.0.x-dev
Status: Fixed » Needs review

@mfb @benjifisher @mullzk Thanks for the feedback on Ubuntu. The backported patch is now on it's way to jammy-proposed and the SRU to Ubuntu 22.04 LTS will likely to happen with 8.1.2-1ubuntu2.5. For unreleased Ubuntu 22.10 aka kinetic it was squashed with 8.1.7-1ubuntu1 as import from Debian unstable.

@xjm @lauriii Cherrio :) Understand it's tricky in core and simple version_compare feels clean. But to be fair it's technical in-precise with enterprise distributions and LTS downstreams of PHP. Would be kind to honor PHP LTS efforts if community and vendors like Canonical, Freexian, RedHat and even Microsoft do the heavy lifting of backporting when upstream already said c'est la vie.

Once the bug fix is released via jammy-updates the Drupal warning will be incorrect. Once the next security update ships via jammy-security the bug fix will reach all professional managed Ubuntu 22.04 installs. While we argued to import >= 8.1.6 from Debian unstable it's against the stable release update policy and hence Canonical declined for LTS so the bug will get fixed like usual with a backport.

catch’s picture

Version: 10.0.x-dev » 9.4.x-dev
Status: Needs review » Fixed

@kraut I've opened a new issue for handling Ubuntu PHP versions at #3307248: Special case Ubuntu PHP versions for some system_requirements() warnings, we've been running into that issue for years, for example in #2670966: Warn users of old PHP versions, but never been able to come up with a satisfactory solution.

benjifisher’s picture

@kraut:

I do not install PHP with apt, because Homebrew and Docker give me more flexibility. But I do use other utilities:

$ vim --version | head -5
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Apr 18 2022 19:26:30)
Included patches: 1-3995
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Huge version with GTK3 GUI.  Features included (+) or not (-):

Of course, Vim is a lot simpler than PHP, and it maintains a simple list of patches between versions. But the point is that it is easy to get the list of patches that have been applied. I do not know how hard it would be to get something like the "Included patches" line added to php -v.

I am not sure what you mean by "Would be kind to honor PHP LTS efforts ...". If what you mean is that there is a way Drupal could take advantage of those efforts to make this warning more accurate, then please explain further. Maybe #3307248: Special case Ubuntu PHP versions for some system_requirements() warnings is the right place to continue that discussion, since this issue is now fixed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

jppo’s picture

Hello,
I am using PHP 8.1.11 and Drupal 8.4.8 and get many kind of error messages when opcache is used.
Yesterday I disable opcache and since 1 day I didn't get any new error messages.
The downside is that the site is significantly less responsive.

cilefen’s picture

@jppo That is a bit mysterious. Would you like to share with the community the text of those error messages? Do so in a new issue with steps to reproduce.

rfmarcelino’s picture

In case you landed here because you have this error (missing classes) after upgrading to Ubuntu 22 LTS, and apt upgrade keeps php 8.1.2, just run
sudo add-apt-repository ppa:ondrej/php
and run apt update && apt upgrade again

andypost’s picture

berdir’s picture

I think #143 is not about the status message, it's about the actual error, which I've already mentioned in that other issue, which is just about removing the status message for ubuntu. I'm fairly certain that this problem is _not_ fixed in Ubuntu 22.04, something about that patch does not seem to be working as it should.

bogdog400’s picture

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).
bogdog400’s picture

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.