php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77205 No E_ERROR level output from a recursive autoloading call
Submitted: 2018-11-26 18:00 UTC Modified: 2018-11-26 19:21 UTC
From: claudio dot luis at aptoide dot com Assigned:
Status: Not a bug Package: SPL related
PHP Version: 7.2.12 OS: Linux (Ubuntu)
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: claudio dot luis at aptoide dot com
New email:
PHP Version: OS:

 

 [2018-11-26 18:00 UTC] claudio dot luis at aptoide dot com
Description:
------------
Whenever a class or interface is autoloaded through the autoload of another class (internally recursive autoload), if such class or interface file is not found in the end (no file loaded/found), no E_ERROR level error is output to the screen (be it console or browser), namely the error reporting a class or interface to not have been found.


In other words, in cases such as:
class A extends B
and
class A implements B

if neither A and B have been loaded yet, once A is autoloaded, so is B, but if the autoloading of B fails, no error is output and the program execution simply halts silently, while if the autoloading of A fails, then the expected error is shown, such as: 
"PHP Fatal error:  Class 'A' not found in ..."


However, if the file containing class A is explicitly loaded beforehand, like so for example:
include_once 'A.php';

then the same test results in a visible error, such as:
"PHP Fatal error:  Interface 'B' not found in ..."


Also, while not shown, in all cases the error is still registered internally and can be fetched with error_get_last().

Test script:
---------------
//A.php (B.php does not exist)
class A implements B
{
    public function doStuff(): void
    {
        echo "Hello World!";
    }
}

//------------------------------------------------------------------

//test.php
//load class and interface files residing in the same directory
spl_autoload_register(function (string $class): void {
    @include_once __DIR__ . '/' . $class . '.php';
}, true);

(new A)->doStuff();

Expected result:
----------------
The following error output to the console or browser:

PHP Fatal error:  Interface 'B' not found in /test.php on line 6

Actual result:
--------------
No error at all is output, but the program execution is halted.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-11-26 18:05 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2018-11-26 18:05 UTC] requinix@php.net
So the bug you're reporting is that when you use @ to suppress errors, you don't see errors?
 [2018-11-26 18:43 UTC] claudio dot luis at aptoide dot com
No, that's not what I intended to report, but now that you mention it, I believe you pretty much nailed it, and the error is on my side, silly me. :)

Essentially, the first include (class A) triggers a second include internally through autoloading (interface B), and the "@" is suppressing the errors of the second, since it's recursive.
That makes sense.

I thought it wasn't really suppressing it since I was seeing the errors in the other use-cases I mentioned, and I noticed a very old similar report still "Open":
https://bugs.php.net/bug.php?id=73323
so I thought this was indeed a bug which wasn't solved yet.

But yeah, it's not a bug... you may close this report.

Sorry and thank you. :)
 [2018-11-26 18:49 UTC] nikic@php.net
Side note, I think we should exclude errors above the warning level from error suppression. @ is usually used to suppress expected warnings, but if something more severe happens in between, that's a hard to debug WSOD.
 [2018-11-26 19:00 UTC] spam2 at rhsoft dot net
> I think we should exclude errors above the warning level from error suppression

yes!

a Fatal Error or Exception you don't see leading to a white page and empty error logs is not that helpful, especially when it comes to deprecation warnings you don't see and after the next php update they ead to a white page - been there with 5.4
 [2018-11-26 19:21 UTC] claudio dot luis at aptoide dot com
I agree with the above.

The use-case that spawned this was an autoloader I did a while ago which has this "@" before the include, because it's expected to fail and it always outputs/logs a warning whenever so (and it's the only case where I used "@").

Although looking at it again, I could just use stream_resolve_include_path to check for the path first and do an include without this suppression in the first place, making my code completely @-free (which I just did).

Having that said, with "@" suppressing even E_ERROR level errors, the program will just halt silently with no further output, and I am not seeing the use case where such a behavior would be useful (that's one of the reasons why I tend to avoid "@").
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Mon Apr 28 08:01:28 2025 UTC