Skip to content

ExceptionTrap discards PHP 8.5 fatal-error backtraces #19571

Description

@jaydenireland

Description

PHP 8.5 is the first PHP release to include a native backtrace with fatal errors. PHP documents this in the PHP 8.5 release notes.

When CakePHP handles a fatal error during shutdown, ExceptionTrap::handleShutdown() reads error_get_last() but only passes its message, file, and line to handleFatalError(). The new trace element is discarded. The resulting FatalErrorException therefore only shows CakePHP's shutdown handler, [internal], and [main], rather than the application call stack that caused the fatal error.

This makes out-of-memory errors especially difficult to diagnose.

On PHP 8.2–8.4, error_get_last() does not provide a trace element, so the existing behaviour should remain unchanged.

Steps to reproduce

  1. Run an application on PHP 8.5 with a low memory limit, such as memory_limit=16M.

  2. Add a call path that exhausts memory:

    final class ReportService
    {
        public function generate(): void
        {
            $this->exhaustMemory();
        }
    
        private function exhaustMemory(): void
        {
            $chunks = [];
            while (true) {
                $chunks[] = str_repeat('x', 1024 * 1024);
            }
        }
    }
  3. Request the controller action that calls ReportService::generate().

Actual behaviour

CakePHP reports the memory error, but the stack trace is limited to the shutdown handler:

Cake\Error\FatalErrorException: Allowed memory size exhausted
Stack Trace:
- CORE/src/Error/ExceptionTrap.php:...
- [internal]:??
- [main]:

Expected behaviour

On PHP 8.5+, CakePHP should preserve and format the fatal-error backtrace supplied by error_get_last(), so the reported exception identifies the application call path (for example, ReportService::generate() and the calling controller action).

Trace arguments should remain omitted to avoid exposing sensitive values.

Possible implementation

Use the trace entry from error_get_last() when it is present, and append a formatted version to the fatal error description before passing it to handleFatalError(). The trace is absent on supported PHP 8.2–8.4 versions, so this can be conditional without changing their output.

CakePHP Version

5.4.1

PHP Version

8.5.4

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions