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

Custom Error Handlers (set_error_handler)

PHP PHP 5.0+ Intermediate
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). PHPStan (listed in detection_hints.tools) can flag the presence of set_error_handler() calls but cannot reliably detect that fatal errors are silently unhandled or that the handler returns the wrong value — those misuse patterns only surface during runtime testing or manual review.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix shows a one-liner handler registration, but correctly fixing the pattern requires also adding register_shutdown_function() + error_get_last(), restoring the previous handler in tests, and ensuring return true — a small but multi-step fix within one component rather than a single-line swap.

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

Closest to 'localised tax' (b3). The handler applies to web, cli, and queue-worker contexts (broad applies_to), but a correctly registered custom error handler is mostly self-contained in a bootstrap/init file. It imposes a persistent but manageable tax: future maintainers must know the handler exists and must restore it in tests, but it doesn't reshape the entire codebase.

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

Closest to 'serious trap' (t7). The misconception field explicitly states the canonical wrong belief: developers assume set_error_handler() catches all errors, but it silently misses E_ERROR and E_PARSE fatal errors. Combined with common mistakes (not returning true, not restoring handler in tests), this contradicts the intuitive expectation that a 'catch-all error handler' truly catches everything, making it a serious trap.

About DEBT scoring →

TL;DR

set_error_handler() lets you replace PHP's default error handling with a custom callback — essential for logging, alerting, and graceful degradation.

Explanation

PHP triggers errors via a global error handler. set_error_handler(callable $handler) replaces it for user-level errors (E_WARNING, E_NOTICE, E_USER_ERROR etc.) but cannot catch E_ERROR, E_PARSE, or E_CORE_ERROR — those still kill the script unless register_shutdown_function() is used. The callback receives ($errno, $errstr, $errfile, $errline). Always restore the previous handler with restore_error_handler() in tests. set_exception_handler() is the equivalent for uncaught exceptions.

Common Misconception

set_error_handler() catches all errors — it cannot catch fatal errors (E_ERROR, E_PARSE). Use register_shutdown_function() + error_get_last() to handle those.

Why It Matters

Custom error handlers let you log errors to external systems, convert them to exceptions, and prevent sensitive paths from leaking in error messages.

Common Mistakes

  • Forgetting to return true from the handler — PHP then executes the internal handler too.
  • Not restoring the previous handler — breaks test isolation.
  • Using set_error_handler() alone without register_shutdown_function() — misses fatal errors.

Code Examples

✗ Vulnerable
set_error_handler(function($errno, $errstr) {
    // Silently ignores — errors disappear
});
✓ Fixed
set_error_handler(function(int $errno, string $errstr, string $errfile, int $errline): bool {
    throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
});

register_shutdown_function(function() {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
        // Log fatal error before script dies
        error_log("Fatal: {$error['message']} in {$error['file']}:{$error['line']}");
    }
});

Added 22 Mar 2026
Views 49
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 0 pings T 1 ping F 2 pings S 1 ping S 1 ping M 1 ping T 0 pings W 1 ping T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 6 Scrapy 6 SEMrush 4 ChatGPT 3 Unknown AI 3 Google 3 Ahrefs 3 Claude 2 Bing 2 Meta AI 1 PetalBot 1
crawler 35 crawler_json 4 pre-tracking 2
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
Register handler with set_error_handler(fn($errno,$errstr,$errfile,$errline) => throw new ErrorException($errstr,0,$errno,$errfile,$errline)) — then catch ErrorException everywhere.
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
set_error_handler
Auto-detectable: ✓ Yes phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✗ Manual fix Fix: Medium Context: Function Tests: Update


✓ schema.org compliant