Upgrade to php8
Set Joomla error reporting to anything but none
Attempt to access site
Access successful
500 error include_once(Cache/Lite.php): Failed to open stream: No such file or directory
PHP8 seems to be throwing this error whenever the included file is missing if the error reporting is anything other than none. J4 does not have this issue as the cache Lite has been removed.
I originally thought this was j3.10 specific but on further though expect the same issue any any J3 rlease.
Labels |
Added:
No Code Attached Yet
|
Title |
|
Thanks Phil. Installing the Cache_Lite pear package did in fact solve the problem. The question I have now though is why? I have caching disabled which I would have thought would not then attempt to perform this include. I do not remember ever having enabled anything in Joomla for this support.
Do you know where the configuration for this would be?
Can you generate a whole stack trace (enable debug mode in global config in Joomla /configuration.php)?
In order to do that I need to uninstall the pear package. I have done so but the problem is no longer occurring. Very strange.
OK, forget that previous comment, I hadn't enabled error reporting. Below is the stack trace:
KExceptionError | Warning [500]
include_once(Cache/Lite.php): Failed to open stream: No such file or directory
.../libraries/src/Cache/Storage/CacheliteStorage.php:347
342 *
343 * @SInCE 3.0.0
344 /
345 public static function isSupported()
346 {
347 @include_once 'Cache/Lite.php';
348
349 return class_exists('\Cache_Lite');
350 }
351 }
include_once() Joomla\CMS\Cache\Storage\CacheliteStorage::isSupported() Joomla\CMS\Cache\Cache::getStores() JFormFieldCacheHandler->getOptions() JFormFieldList->getInput() Joomla\CMS\Form\FormField->__get() JFormFieldList->__get() include() Joomla\CMS\Layout\FileLayout->render() Joomla\CMS\Layout\LayoutHelper::render() include() ConfigViewCmsHtml->loadTemplate() include() JViewHtml->render() ConfigViewApplicationHtml->render() ConfigControllerDisplay->execute() require_once() Joomla\CMS\Component\ComponentHelper::executeComponent() Joomla\CMS\Component\ComponentHelper::renderComponent() Joomla\CMS\Application\AdministratorApplication->dispatch() Joomla\CMS\Application\AdministratorApplication->doExecute() Joomla\CMS\Application\CMSApplication->execute()
include_once()
.../libraries/src/Cache/Storage/CacheliteStorage.php:347
342 *
343 * @SInCE 3.0.0
344 /
345 public static function isSupported()
346 {
347 @include_once 'Cache/Lite.php';
348
349 return class_exists('\Cache_Lite');
350 }
351 }
Joomla\CMS\Cache\Storage\CacheliteStorage::isSupported()
.../libraries/src/Cache/Cache.php:128
123 {
124 continue;
125 }
126
127 // Sweet! Our class exists, so now we just need to know if it passes its test method.
128 if ($class::isSupported())
129 {
130 // Connector names should not have file extensions.
131 $handler = str_ireplace('Storage.php', '', $fileName);
132 $handler = str_ireplace('.php', '', $handler);
133 $handlers[] = strtolower($handler);
Joomla\CMS\Cache\Cache::getStores()
.../libraries/joomla/form/fields/cachehandler.php:43
38 protected function getOptions()
39 {
40 $options = array();
41
42 // Convert to name => name array.
43 foreach (JCache::getStores() as $store)
44 {
45 $options[] = JHtml::('select.option', $store, JText::('JLIB_FORM_VALUE_CACHE_' . $store), 'value', 'text');
46 }
47
48 $options = array_merge(parent::getOptions(), $options);
JFormFieldCacheHandler->getOptions()
.../libraries/joomla/form/fields/list.php:58
53
54 // Initialize JavaScript field attributes.
55 $attr .= $this->onchange ? ' onchange="' . $this->onchange . '"' : '';
56
57 // Get the field options.
58 $options = (array) $this->getOptions();
59
60 // Create a read-only list (no name) with hidden input(s) to store the value(s).
61 if ((string) $this->readonly == '1' || (string) $this->readonly == 'true')
62 {
63 $html[] = JHtml::_('select.genericlist', $options, '', trim($attr), 'value', 'text', $this->value, $this->id);
JFormFieldList->getInput()
.../administrator/components/com_fabrik/classes/310/FormField.php:425
420
421 case 'input':
422 // If the input hasn't yet been generated, generate it.
423 if (empty($this->input))
424 {
425 $this->input = $this->getInput();
426 }
427
428 return $this->input;
429
430 case 'label':
Joomla\CMS\Form\FormField->__get()
.../libraries/joomla/form/fields/list.php:277
272 if ($name == 'options')
273 {
274 return $this->getOptions();
275 }
276
277 return parent::__get($name);
278 }
279 }
JFormFieldList->__get()
.../layouts/joomla/content/options_default.php:33
28
29 <div class="control-group">
30 showlabel) || $displayData->showlabel) : ?>
31
And there we have the clue I needed
‘KExceptionError’
this is not a Joomla issue - this is an issue in the JoomlaTools (DocMan, LogMan suite of tools) library framework overwriting the default and Joomla error handlers and disabling the error suppression
Status | New | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2021-09-07 11:56:33 |
Closed_By | ⇒ | skurvish |
OK, great! I will revert back to them. Thanks for finding that. I am closing this issue.
Status | Closed | ⇒ | New |
Closed_Date | 2021-09-07 11:56:33 | ⇒ | |
Closed_By | skurvish | ⇒ |
OK, so now I seem to be in the middle. Here is what Joomlatools has to say about it:
Happy to assist you. From the report info you link too the error you are experiencing is Joomla error.
Our framework has a build in more advanced error handling and error reporting system that is activated when you put your site into debug mode. We promote PHP execution errors too Exceptions inline with the changes made in PHP7: "PHP 7 changes how most errors are reported by PHP. Instead of reporting errors through the traditional error reporting mechanism used by PHP 5, most errors are now reported by throwing Error exceptions." "https://www.php.net/manual/en/language.errors.php7.php"
An error report is generated from the exception including a backtrace if possible, a reference to KExceptionError is included since that is the class that wraps the error and handles it. There are different classes for different types of exceptipns. In this case it's an Error throw an Exception. This doesn't mean however that the error is a problem with any of our extensions. We just caught it. The actual error is the one you reported initially: 500 error include_once(Cache/Lite.php): Failed to open stream: No such file or directory
This does indeed sound like a bug in Joomla 3.10 and the information you provided in the bug report is correct. The "Cache/Lite.php" file doesn't exist or is not readable. A quick check in the Joomla bug trackers reveils follwoing related issues:
Looking at the code shows that the error is generated: https://github.com/joomla/joomla-cms/blob/3.10-dev/libraries/src/Cache/Storage/CacheliteStorage.php#L347
public static function isSupported()
{
@include_once 'Cache/Lite.php';
return class_exists('\Cache_Lite');
}
Joomla is using the error supressor to supress the include error. This no longer works for certain fatal errors. More info here: https://php.watch/versions/8.0/fatal-error-suppression.
Error supression shouldn't be used in libraries, it's considered a code smell. The right solution here would be to either throw an exception and catch it, or to just check if the "Cache/Lite.php" file exists instead of trying to require it.
Hope helps,
Joomla is using the error supressor to supress the include error. This no longer works for certain fatal errors. More info here: https://php.watch/versions/8.0/fatal-error-suppression.
Correct. And probably something that can be improved.
Error supression shouldn't be used in libraries, it's considered a code smell.
Again correct, but there are historical reasons why it is there, and therefore justified reasons through libraries why error suppression is - sparingly - used. Its use is sparingly and even Joomla contributors limit their use of it.
or to just check if the "Cache/Lite.php" file exists instead of trying to require it.
Joomla could do that. Yes.
But also for the record, the article https://php.watch/versions/8.0/fatal-error-suppression clearly states that using the error suppression on include IS A VALID CASE ... as is file operations.
Also failing to include is NOT a fatal error, but is just a WARNING - THAT CAN, in ALL PHP VERSIONS be suppressed correctly, including in PHP 8 - see test case here:
and then see it create warnings:
So... no we cannot catch the exception, because it doesnt, under normal circumstances, generate an exception, all it generates is....
I have tested this up to PHP 8.1 RC 2 and the above facts are correct.
So... .that leads you back to JoomlaTools who manipulate error handling...
include_once
raises warnings whereas require_once
would be a fatal error if it could not load the file.
On further reflection and testing, this is not a Joomla issue.
As evidenced by my testing previously and again today, the failure of an include_once
to find the file to include raises a warning in PHP 7 and in PHP 8 and is correctly suppressed by the error suppressor on both occasions in both PHP versions
It is never raised to a 500 Internal Server Error and is never raising an exception. This is correct and by design.
The only difference between this by design, and your error message, is that JoomlaTools framework has raised this PHP Warning into a PHP Exception. This is wrong, and not a Joomla fault.
I installed com_docman 3.5.4 to Joomla 3.10.1 to see if I could replicate this issue but I was unable to ever replicate your reported issue at all.
I could provide you with the latest version but it is licensed so should not. Disabling the Joomlatools framework plugin gets around the issue for now, but I think between the two entities something needs to be done to allow the two to coexist. Not my pervue.
Disabling the Joomlatools framework plugin gets around the issue for now
Is this confirming that once you disable the JoomlaTools framework, you no longer have this issue?
That is correct.
Then I refer you to my initial comment. This is not a Joomla issue. Joomla, and PHP are doing what Joomla and PHP are designed to do. JoomlaTools framework is escalating a PHP Warning (which is correctly suppressed in all supported PHP versions) to an Exception and killing the page load.
think between the two entities something needs to be done to allow the two to coexist.
Joomla and PHP are doing the standard thing. Escalating a suppressed PHP Warning and converting it into an Exception is plain wrong and I would have expected better of Johans team.
This issue can be closed.
@PhilETaylor Thanks for the assistance. You are 100% right, I was a bit too fast in my initial assessment yesterday. Done some in-depth testing today and can confirm that warnings generated by include
are properly suppressed.
The problem stems from the local setup used by @skurvish. He Is running with xdebug
enabled. Only when xdebug is enabled Joomlatools Framework error handler is not suppressing warnings in PHP8. This is by design, we develop locally with xdebug enabled and turn error reporting to max to make sure we don't miss any errors, warnings or notices.
For the code in Joomla 3.10 you could consider changing the check error suppressors remain a code smell and are best refactored out. You can use stream_resolve_include_path
for this.
From
public static function isSupported()
{
@include_once 'Cache/Lite.php';
return class_exists('\Cache_Lite');
}
to
public static function isSupported()
{
if(stream_resolve_include_path('Cache/Lite.php')) {
include_once ‘Cache/Lite.php’;
}
return class_exists('\Cache_Lite');
}
Change might not be worth it with Cache_Lite no longer part of Joomla 4.
Status | New | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2021-09-08 13:02:14 |
Closed_By | ⇒ | skurvish |
As you see above.
I am now closing this issue.
You are 100% right
Said no one ever :) haha.
No worries.
Would you mind proposing an PR against 3.10-dev @johanjanssens so it can be patched in 3.10 and we dont get issues on PHP8?
Your post is proof that you did not read the whole thread.
There will never be an issue on PHP8.
Tl:dr; this situation only occurs because JoomlaTools reconfigures error reporting when xdebug is installed and promotes a PHP warning into an exception.
Even in PHP8 it will still be a correctly suppressed warning just like it is today. One of the only real uses for error surppression as evidenced by the blog post they provided.
there is no point removing one error suppression and not all the others throughout Joomla.
Yes it could be done but for no real gain apart from with compatibility with the JoomlaTools framework.
I have read the things about xdebug and the JoomlaTools Framework but wouldt it be "the better way" to add such check over supressing error messages? Maybe also for similiar other places?
Now you changed your tune haha
Before it was about PHP8 issues
Now you say you want it because it’s the better way
PRs welcome etc etc lmao
Sent from my iPhone
On 8 Sep 2021, at 14:47, Tobias Zulauf @.***> wrote:
I have read the things about xdebug and the JoomlaTools Framework but wouldt it be "the better way" to add such check over supressing error messages? Maybe also for similiar other places?—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
From my understanding this is an php8 issue only as only there the JoomlaTools thing kicks in but the error supressing is a general thing that should be avoided when there are better solutions.
or to just check if the "Cache/Lite.php" file exists instead of trying to require it.
Joomla could do that. Yes.
That are your own words :D so what is the problem in asking for a PR to add the check thats proposed?
so what is the problem in asking for a PR to add the check thats proposed?
What is the point in fixing a single error suppression in a single feature that is hardly used by anyone (cache lite) and that is already deprecated and removed from Joomla 4, and that requires at least 4 specific things (PHP8, JoomlaTools, XDebug AND removal of cache_lite from previously working server) in order to trigger...
This is not really fixing anything except a very very very edge case. There are bigger issues to resolve (like why people cannot use CloudFlare and Joomla 4!)
Oh the irony here is that out of the 783 instances of error suppression in my code base right now, (if you ignore restore.php which has over 209 because its dealing with file operations) a large percentage, are from JoomlaTools framework and docman...
There you go - its now part of the official Joomla Coding Standards:
I confirm that the above commit fixes this issue. Thank you all and sorry about the hours invested in this very very very edge case.
Thanks. @PhilETaylor
@skurvish can you submit your test result on the PR that has been created? #35507 Thanks!
This is not a Joomla issue.
I cannot replicate this with the steps to reproduce. I believe the ket thing you are not telling us is that your site is already configured to use Cache_Lite in Joomla Global Config before you upgraded PHP.
There is only one place in Joomla 3 code that attempts to
include_once
theCache/Lite.php
file and that is injoomla-cms/libraries/src/Cache/Storage/CacheliteStorage.php
Line 347 in 742de2e
However, even if I set error_reporting to development and display_errors on, I still dont get a 500 Internal Server error like you describe, all I can get is this when accessing Global Config (the only place that calls the above code)
Therefore there must be something else going on with your site.
Also note, that probably all the main contributors to Joomla core work all day every day with error reporting set to development and mostly now with PHP 8, if your steps to reproduce were accurate we would probably have seen this issue before.
The Solution - install Cache_Lite for the new PHP version you are running:
Cache_Lite is not shipped with Joomla and is not shipped with PHP - it is a pear installable extension and thus NEEDS TO BE INSTALLED for each series of PHP you run.
What I believe you have done, is upgrade to PHP 8- but you have not correctly configured your PHP 8 the same way you have your previous versions of PHP - i.e you have not yet installed Cache_Lite using the pear distribution.
You need to install Cache_Lite using pear for your new PHP version - then Joomla can include it
However, please note https://pear.php.net/package/Cache_Lite/ package is not maintained, and is unlikely to continue working for long. The last version 1.8.3 was released in 2019, and thus predates PHP 8 and therefore might not even be compatible (Ive not tested)
What is for certain though, is this is not a Joomla root caused issue.