← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Exception Hierarchy (Throwable, Error, Exception)

PHP PHP 7.0+ Intermediate
debt(d5/e1/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan and psalm, both static analysis tools, as the tools that catch the `catch (Exception` pattern. This is not a default linter catch (d3) nor a compiler error (d1); it requires running a specialist static analyser configured to flag incomplete catch hierarchies.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1). The quick_fix states: replace `catch (Exception $e)` with `catch (\Throwable $t)` — a literal single-line substitution. Even catching specific subclasses is a minimal, local change at each catch site.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to covers web, cli, and queue-worker contexts (broad PHP usage), but the impact is scoped to error-handling code only. It doesn't shape the overall architecture; it is a persistent awareness tax at every catch block rather than a system-wide gravitational pull.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field states explicitly: developers believe `catch (Exception $e)` catches everything, but it silently misses all Error subclasses (TypeError, ParseError, etc.) which only implement Throwable. This directly contradicts intuition from other languages (Java, C#) where a top-level Exception catch is truly exhaustive, making it a cross-ecosystem behavioural contradiction rather than just a documented gotcha.

About DEBT scoring →

TL;DR

PHP 7+ unified exceptions and fatal errors under the Throwable interface — catch Throwable to handle both Error and Exception in one block.

Explanation

PHP 7 introduced Throwable as the root interface. Exception (user exceptions) and Error (engine errors like TypeError, ParseError, ArithmeticError) both implement it. Before PHP 7, fatal errors like calling undefined functions were uncatchable. Now: catch (\Throwable $t) catches everything. catch (\Error $e) catches engine errors. catch (\Exception $e) catches application exceptions. Key subclasses: TypeError (wrong types), ValueError (invalid argument values), ArithmeticError / DivisionByZeroError, ParseError, Error.

Common Misconception

catch (Exception $e) catches everything — it misses Error subclasses (TypeError, ParseError etc.) which only implement Throwable, not Exception.

Why It Matters

Understanding the hierarchy prevents silently missing engine errors and enables writing catch blocks that handle exactly the right error class.

Common Mistakes

  • Catching Exception when Error subclasses are possible — use Throwable.
  • Not distinguishing between recoverable errors (TypeError from user input) and programming errors (wrong arg type in internal code).
  • Swallowing Throwable in catch blocks without logging.

Code Examples

✗ Vulnerable
try {
    $result = intdiv($a, 0);
} catch (Exception $e) {
    // Misses DivisionByZeroError — it's an Error, not Exception
    echo "caught";
}
✓ Fixed
try {
    $result = intdiv($a, 0);
} catch (DivisionByZeroError $e) {
    $result = 0; // specific handling
} catch (\TypeError $e) {
    throw new InvalidArgumentException('Numeric values required', 0, $e);
} catch (\Throwable $t) {
    // Last resort — log everything
    logger()->critical('Unhandled', ['exception' => $t]);
    throw $t;
}

Added 22 Mar 2026
Views 57
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 3 pings F 1 ping S 2 pings S 2 pings M 2 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 2 pings T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Scrapy 10 Amazonbot 8 Perplexity 6 ChatGPT 4 Google 4 SEMrush 4 Unknown AI 3 Ahrefs 3 Meta AI 2 Claude 2 PetalBot 1
crawler 42 crawler_json 3 pre-tracking 2
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
Use catch (\Throwable $t) to catch both Error and Exception — or catch specific subclasses (TypeError, DivisionByZeroError) for precise handling.
📦 Applies To
PHP 7.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
catch (Exception
Auto-detectable: ✓ Yes phpstan psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✗ Manual fix Fix: Low Context: Function Tests: Update
CWE-390 CWE-755


✓ schema.org compliant