Preserve Stack Trace
ID |
php.preserve_stack_trace |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Php |
Tags |
exception-handling, reliability |
Description
Reports a throw new SomeException(…) inside a catch block that does not pass the caught
exception to the new exception. The original exception, and the stack trace it carries, is
then lost.
Rationale
When an exception is caught and a new one is thrown to add context, the caught exception
should be forwarded as the cause. PHP exceptions accept a previous exception as the third
constructor argument ($previous); chaining it preserves the full trace, which
getPrevious() and log formatters rely on for root-cause analysis. Throwing a fresh
exception that ignores the caught one hides where the failure actually originated. A bare
rethrow (throw $e;) keeps the chain intact and is therefore fine.
<?php
try {
$this->load();
} catch (\RuntimeException $e) {
throw new ServiceException('load failed'); // FLAW — drops $e and its trace
}
try {
$this->load();
} catch (\RuntimeException $e) {
throw new ServiceException('load failed', 0, $e); // OK — forwards $e as the previous exception
}