symfony/error-handler
Converts PHP errors into catchable exceptions and renders rich debug pages, with production-safe fallbacks
Repository Health
Technical Analysis
The Symfony ErrorHandler component intercepts PHP’s native error and exception handling to make errors easier to debug in development and safer to handle in production. ErrorHandler::register() converts PHP errors/warnings/notices into catchable \ErrorException-family exceptions (unless silenced via @), while Debug::enable() additionally installs a rich HTML error renderer showing stack traces, source code context, and variable dumps (via symfony/var-dumper) for uncaught exceptions during development.
Beyond error interception, it includes DebugClassLoader, a Composer class-loader wrapper that validates class/method signatures against parent declarations and PHPDoc annotations at autoload time, surfacing type mismatches and deprecated-parent-usage as early, actionable warnings rather than silent bugs. In production, the same component swaps to minimal, non-leaking error pages so stack traces and file paths are never exposed to end users.
What You Get
ErrorHandler(731 lines) — a registered PHP error handler that converts errors/warnings into exceptions and dispatches uncaught-exception renderingDebug::enable()— a one-line entry point that wires up error handling, exception handling, and class-loading checks together for local developmentDebugClassLoader(1413 lines) — validates method signatures against parent/interface declarations and PHPDoc types at autoload time, catching type errors and deprecated API usage early- HTML and other
ErrorRendererimplementations (src/ErrorRenderer) producing readable, source-context-aware error pages for uncaught exceptions in debug mode BufferingLogger, a minimal PSR-3 logger that buffers log records in memory — useful for capturing logs that occur before a real logger is available during bootstrap
Common Use Cases
- Converting silent PHP notices/warnings into catchable exceptions so bugs surface immediately instead of failing silently
- Getting readable stack-trace-and-source-context error pages during local development instead of PHP’s default error output
- Catching type mismatches between a class and the interface/parent it implements at autoload time via
DebugClassLoader - Ensuring production deployments never leak stack traces or file paths in error responses shown to end users
Under The Hood
Architecture — ErrorHandler (ErrorHandler.php) registers itself via PHP’s set_error_handler()/set_exception_handler(), translating raised errors into \ErrorException (or Symfony’s own SilencedErrorContext-aware equivalents when the @ operator was used) so calling code and downstream frameworks can catch them like any other exception. Uncaught exceptions are routed to an ErrorRenderer (src/ErrorRenderer) chosen based on context — HTML for browser requests in debug mode, a minimal safe fallback otherwise — with the HTML renderer pulling in symfony/var-dumper to produce interactive variable dumps alongside the stack trace. DebugClassLoader (1413 lines, by far the largest file) wraps Composer’s autoloader: whenever a class is loaded, it reflects over the class’s methods and compares signatures/PHPDoc types against parent classes and implemented interfaces, emitting deprecation or type-mismatch warnings through trigger_deprecation()-style notices rather than waiting for a runtime type error to surface downstream. BufferingLogger implements PSR-3’s LoggerInterface purely in-memory, intended for the narrow bootstrap window before a real logger service is constructed. Tech Stack — PHP 8.4.1+, PSR-4 autoloaded under Symfony\Component\ErrorHandler, with dependencies on psr/log and symfony/var-dumper; ships a bin/patch-type-declarations console script (registered via composer’s bin field) for a specific migration use case. Split from the symfony/symfony monorepo like other Symfony components. Code Quality — A dedicated Tests/ directory (excluded from the autoload classmap) covers both the error-interception logic and the more subtle DebugClassLoader signature-checking edge cases; the sheer scope of DebugClassLoader (1413 lines handling reflection across PHP’s inheritance, interface, and trait rules) reflects the inherent complexity of correctly validating type compatibility across PHP’s OOP model. API Design — The common path is a single call, Debug::enable(), in a development bootstrap file; production usage is typically just ErrorHandler::register() without the debug renderer, keeping the integration surface intentionally tiny relative to the depth of what happens internally.