diff --git a/app/Views/errors/cli/error_exception.php b/app/Views/errors/cli/error_exception.php
index f24e98fb9a49..98d83b0ed3a6 100644
--- a/app/Views/errors/cli/error_exception.php
+++ b/app/Views/errors/cli/error_exception.php
@@ -3,17 +3,26 @@
use CodeIgniter\CLI\CLI;
// The main Exception
-CLI::newLine();
CLI::write('[' . get_class($exception) . ']', 'light_gray', 'red');
-CLI::newLine();
CLI::write($message);
-CLI::newLine();
CLI::write('at ' . CLI::color(clean_path($exception->getFile()) . ':' . $exception->getLine(), 'green'));
CLI::newLine();
+$last = $exception;
+
+while ($prevException = $last->getPrevious()) {
+ $last = $prevException;
+
+ CLI::write(' Caused by:');
+ CLI::write(' [' . get_class($prevException) . ']', 'red');
+ CLI::write(' ' . $prevException->getMessage());
+ CLI::write(' at ' . CLI::color(clean_path($prevException->getFile()) . ':' . $prevException->getLine(), 'green'));
+ CLI::newLine();
+}
+
// The backtrace
if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) {
- $backtraces = $exception->getTrace();
+ $backtraces = $last->getTrace();
if ($backtraces) {
CLI::write('Backtrace:', 'green');
diff --git a/app/Views/errors/html/error_exception.php b/app/Views/errors/html/error_exception.php
index 1c094d728872..406b48ec6772 100644
--- a/app/Views/errors/html/error_exception.php
+++ b/app/Views/errors/html/error_exception.php
@@ -44,6 +44,29 @@
+
+ getPrevious()) {
+ $last = $prevException;
+ ?>
+
+
+ Caused by:
+ = esc(get_class($prevException)), esc($prevException->getCode() ? ' #' . $prevException->getCode() : '') ?>
+
+ = nl2br(esc($prevException->getMessage())) ?>
+ getMessage())) ?>"
+ rel="noreferrer" target="_blank">search →
+ = esc(clean_path($prevException->getFile()) . ':' . $prevException->getLine()) ?>
+
+
+
+
+
diff --git a/system/Debug/BaseExceptionHandler.php b/system/Debug/BaseExceptionHandler.php
index 0330c53cf97c..8b67d2153f9f 100644
--- a/system/Debug/BaseExceptionHandler.php
+++ b/system/Debug/BaseExceptionHandler.php
@@ -67,7 +67,14 @@ abstract public function handle(
*/
protected function collectVars(Throwable $exception, int $statusCode): array
{
- $trace = $exception->getTrace();
+ // Get the first exception.
+ $firstException = $exception;
+
+ while ($prevException = $firstException->getPrevious()) {
+ $firstException = $prevException;
+ }
+
+ $trace = $firstException->getTrace();
if ($this->config->sensitiveDataInTrace !== []) {
$trace = $this->maskSensitiveData($trace, $this->config->sensitiveDataInTrace);
diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php
index a9887fba15ce..4b3e5cf3ea3e 100644
--- a/system/Debug/Exceptions.php
+++ b/system/Debug/Exceptions.php
@@ -125,22 +125,31 @@ public function exceptionHandler(Throwable $exception)
[$statusCode, $exitCode] = $this->determineCodes($exception);
if ($this->config->log === true && ! in_array($statusCode, $this->config->ignoreCodes, true)) {
- log_message('critical', "{message}\nin {exFile} on line {exLine}.\n{trace}", [
+ log_message('critical', get_class($exception) . ": {message}\nin {exFile} on line {exLine}.\n{trace}", [
'message' => $exception->getMessage(),
'exFile' => clean_path($exception->getFile()), // {file} refers to THIS file
'exLine' => $exception->getLine(), // {line} refers to THIS line
'trace' => self::renderBacktrace($exception->getTrace()),
]);
+
+ // Get the first exception.
+ $last = $exception;
+
+ while ($prevException = $last->getPrevious()) {
+ $last = $prevException;
+
+ log_message('critical', '[Caused by] ' . get_class($prevException) . ": {message}\nin {exFile} on line {exLine}.\n{trace}", [
+ 'message' => $prevException->getMessage(),
+ 'exFile' => clean_path($prevException->getFile()), // {file} refers to THIS file
+ 'exLine' => $prevException->getLine(), // {line} refers to THIS line
+ 'trace' => self::renderBacktrace($prevException->getTrace()),
+ ]);
+ }
}
$this->request = Services::request();
$this->response = Services::response();
- // Get the first exception.
- while ($prevException = $exception->getPrevious()) {
- $exception = $prevException;
- }
-
if (method_exists($this->config, 'handler')) {
// Use new ExceptionHandler
$handler = $this->config->handler($statusCode, $exception);
@@ -325,7 +334,14 @@ protected function render(Throwable $exception, int $statusCode)
*/
protected function collectVars(Throwable $exception, int $statusCode): array
{
- $trace = $exception->getTrace();
+ // Get the first exception.
+ $firstException = $exception;
+
+ while ($prevException = $firstException->getPrevious()) {
+ $firstException = $prevException;
+ }
+
+ $trace = $firstException->getTrace();
if ($this->config->sensitiveDataInTrace !== []) {
$trace = $this->maskSensitiveData($trace, $this->config->sensitiveDataInTrace);
diff --git a/user_guide_src/source/installation/upgrade_444.rst b/user_guide_src/source/installation/upgrade_444.rst
index b3773947efd9..e21a1850d613 100644
--- a/user_guide_src/source/installation/upgrade_444.rst
+++ b/user_guide_src/source/installation/upgrade_444.rst
@@ -16,6 +16,14 @@ Please refer to the upgrade instructions corresponding to your installation meth
Mandatory File Changes
**********************
+Error Files
+===========
+
+Update the following files to show correct error messages:
+
+- app/Views/errors/cli/error_exception.php
+- app/Views/errors/html/error_exception.php
+
****************
Breaking Changes
****************