symfony/error-handler: PHP error management for Symfony and standalone projects
Provides tools to manage errors and ease debugging PHP code
At a glance
- What is it?
- The ErrorHandler component turns PHP errors, warnings and fatal conditions into readable output and testable exceptions. It ships as a standalone Composer package, but its real value shows up when you use Debug::enable() and ErrorHandler::call() together.
- Who is it for?
- Adopt symfony/error-handler if you write PHP that needs consistent error rendering or if you want @-suppressed failures to surface as exceptions during testing. Skip it if your application already runs inside a full Symfony framework install, because the component is wired in for you and adding it separately duplicates configuration.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What symfony/error-handler actually solves for PHP developers
PHP's default error output is a plain text line and a stack trace that stops at the interpreter boundary. Fatal errors terminate the request with no structured payload, and the @ silence operator hides failures that later cause confusing behaviour elsewhere. The ErrorHandler component addresses both problems. It registers handlers that capture PHP errors and uncaught exceptions, renders them through a configured renderer, and offers ErrorHandler::call() as a wrapper that converts any failure inside the callback into a thrown exception. The README describes the package as providing tools to manage errors and ease debugging PHP code, and the repository layout confirms that scope: ErrorHandler.php, Debug.php, DebugClassLoader.php, plus Error/, ErrorEnhancer/, ErrorRenderer/ and Exception/ directories. It is aimed at PHP developers who want this behaviour without pulling in the full framework, and at framework users who want to understand what runs underneath.
How Debug::enable, ErrorHandler and DebugClassLoader fit together
Three entry points exist, and the README shows that Debug::enable() turns on all of them at once. ErrorHandler::register() installs the error and exception handlers by itself. DebugClassLoader::enable() installs a separate autoloader wrapper that reports class loading problems, which is why it lives in its own file at the repository root. The rendering path runs through ErrorRenderer/, where HtmlErrorRenderer is the class the README references for template overrides. ErrorEnhancer/ sits alongside it and is responsible for adding context to errors before they reach a renderer. BufferingLogger.php and ThrowableUtils.php at the root are supporting pieces rather than public entry points. The practical consequence is that you can adopt the exception conversion without the HTML output, or the HTML output without the autoloader checks, depending on which of the three calls you make.
Installing symfony/error-handler and a first real use
The README gives a single Composer command, and the package has no framework requirement stated in the README.
composer require symfony/error-handlerAfter installation, the README's getting started example enables every feature with one call. If you only want the error handler, the README shows the alternative call commented out directly beneath it.
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\ErrorHandler\ErrorHandler;
use Symfony\Component\ErrorHandler\DebugClassLoader;
Debug::enable();
// or enable only one feature
//ErrorHandler::register();
//DebugClassLoader::enable();The third piece in the README is ErrorHandler::call(), which wraps a closure so that any failure inside it throws a PHP exception, including failures that use the @ silence operator. The README's example reads a JSON file, adds a read_at field, and writes it back.
$data = ErrorHandler::call(static function () use ($filename, $datetimeFormat) {
// if any code executed inside this anonymous function fails, a PHP exception
// will be thrown, even if the code uses the '@' PHP silence operator
$data = json_decode(file_get_contents($filename), true);
$data['read_at'] = date($datetimeFormat);
file_put_contents($filename, json_encode($data));
return $data;
});What you should see is the returned array on success. On failure, the call throws instead of returning a partial result, so a missing file or malformed JSON stops the surrounding code rather than producing a warning you might miss.
For a custom generic error page when debug is off, the README gives one static call before any of the above.
HtmlErrorRenderer::setTemplate('/path/to/custom/error.html.php');The README does not document which variables that template receives, so treat the path as the only confirmed part of this call.
Where the component stops being the right tool
Debug::enable() is a development switch. The README frames the custom template as the option for when debug is not enabled, which implies that debug output and production output are distinct modes rather than one configuration. If you enable debug in a production request, the rendered error page is the debug page, and the component does not decide that for you. The second limitation is narrower: ErrorHandler::call() converts failures into exceptions only for code executed inside the callback. Code that runs before or after the call keeps PHP's normal error behaviour. Third, the README documents no rollback or teardown path. There is no unregister call shown, so a long-running process that enables the handler once keeps it for the life of the process. That matters for workers, queue consumers and test runners that expect to restore the previous handler between jobs. Finally, the component handles errors; it does not log them to a destination on its own. BufferingLogger.php buffers, and the README does not describe where buffered entries go.
How it differs from Whoops and from framework error pages
Whoops is the closest well-known alternative, and the difference is architectural rather than cosmetic. Whoops centres on a pretty error page for uncaught exceptions. symfony/error-handler centres on a handler stack that also covers PHP errors, class loading diagnostics through DebugClassLoader, and exception conversion through ErrorHandler::call(). If your only goal is a nicer stack trace page, Whoops covers that with less surface area. If you want @-suppressed failures to become exceptions you can assert on in tests, Whoops does not offer that mechanism. The second comparison is with a full Symfony application, where the component is already registered as part of the framework. Installing the standalone package inside such an application gives you a second registration path and a second set of renderer configuration, which is a reason to leave it alone rather than a reason to adopt it.
Versioning, licence and what upgrades cost
The repository is on the 8.2 default branch, and the recent releases listed are v8.1.5, v7.4.17 and v6.4.44, all published on 2026-08-22. Three maintained lines receiving releases on the same day means the project backports fixes rather than only moving forward. The last push to the repository was on 2026-09-22, six days before this article's date, so the branch is receiving commits. The licence is MIT, which permits commercial use and modification provided the copyright notice and permission notice are retained; that is a statement about the licence text, not legal advice, and your own counsel should confirm how it applies to your distribution. Upgrade cost depends on which line you are on. The CHANGELOG.md at the repository root is the file to read before moving between major versions, and composer.json states the PHP version constraint you need to satisfy. The README does not document a deprecation policy or a support window, so the release dates above are the only maintenance signal available from the README.
Editorial conclusion
Adopt symfony/error-handler if you write PHP that needs consistent error rendering or if you want @-suppressed failures to surface as exceptions during testing. Skip it if your application already runs inside a full Symfony framework install, because the component is wired in for you and adding it separately duplicates configuration. Before relying on it, check the 8.2 branch against your PHP version in composer.json, and confirm that HtmlErrorRenderer::setTemplate() matches the template variables your custom file expects.
Frequently asked questions
What is symfony/error-handler?
It is a standalone PHP component that provides tools to manage errors and ease debugging PHP code. It is installable on its own with Composer and exposes Debug, ErrorHandler, DebugClassLoader and the renderer classes.
How do I install symfony/error-handler?
Run composer require symfony/error-handler. The README gives that as the only installation step, after which you enable features by calling Debug::enable() or the individual registration methods.
Does symfony/error-handler turn warnings into exceptions?
ErrorHandler::call() does this for code inside the callback it wraps. The README states that if any code executed inside the anonymous function fails, a PHP exception will be thrown, even if the code uses the @ silence operator.
Can I use symfony/error-handler outside a Symfony application?
Yes. It is a Composer package with its own repository and README, and the getting started example uses only classes from the component's namespace. Nothing in the README requires a framework application to be present.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/symfony-error-handler)