Open-source project
symfony/error-handler avatar
symfony/error-handler

symfony/error-handler: three switches, a monorepo pull request, and a sample that stops mid sentence

Provides tools to manage errors and ease debugging PHP code

2,673 stars21 forksPHPMIT

At a glance

What is it?
A small PHP component split into its own repository, offering Debug, ErrorHandler and DebugClassLoader as three separately enableable entry points. The visible page is short, its code sample ends inside a comment, and the 8.2 branch has no release tag in the recent list.
Who is it for?
Reach for this when you are working on plain PHP outside a full framework stack and want error to exception conversion and a debug front end without assembling them yourself, and skip it if you expected configuration knobs: the visible page names no environment variable, no service definition and no PHP version requirement. Three things to check in your own clone first.
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 10 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 November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • symfony/error-handler2,673 ★ · +0
Star history
Repository2026-10-042026-11-14
symfony/error-handler2.7k2.7k

0 Stars in the last 41 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Three entry points, and a directory the page never names

The visible page names three things you can turn on, and all three appear in a single snippet.

php
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 tree behind that page is wider. Alongside the three classes sit BufferingLogger.php and ThrowableUtils.php at the root, and six directories: Error, ErrorEnhancer, ErrorRenderer, Exception, Internal, Command, plus Resources and Tests. ErrorEnhancer is the one directory with no counterpart anywhere in the visible text, and ThrowableUtils.php at the root has no import line either. So the page documents three switches while the package carries a logger, a throwable helper, an error enhancer, an internal namespace, a console command directory and a test suite.

The sample closes a call it never finishes and captures two undefined variables

The second snippet is the one that shows the shape of the API, and it does not survive contact with a copy and paste.

php
$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 u

Two things are missing from what the page shows. The comment line ends on the fragment even if the code u, so the sentence describing the behavior is unfinished, and the call itself is never closed: there is no return, no assignment target beyond the opening line, and no closing parenthesis. The closure also captures $filename and $datetimeFormat, and neither variable is defined anywhere above it, so the snippet cannot run as printed. Read it as an outline of the calling convention, a static closure handed to ErrorHandler::call, rather than as code you can paste into a file.

Debug::enable() is the bundle, the other two are opt in

The comment above the two disabled lines reads or enable only one feature, which is the whole configuration story on this page. Debug::enable() is the combined switch. ErrorHandler::register() and DebugClassLoader::enable() are the same machinery taken one piece at a time, and both appear in the snippet already written out with their class names imported at the top. Nothing else on the page changes that choice: there is no flag, no environment variable, no configuration file name and no framework bundle class. So the decision you are making is which of the three you call at bootstrap and nothing more. For a project already inside Symfony, the framework wires this component itself and the visible page offers no guidance on that path, since it describes no bundle class, no services.yaml entry and no kernel event.

The custom template applies only when debug is off

One more capability sits in the snippet, commented out.

php
// If you want a custom generic template when debug is not enabled
// HtmlErrorRenderer::setTemplate('/path/to/custom/error.html.php');

Two details matter. The gate is explicit: the custom template is the generic one used when debug is not enabled, so it is the production path and not a way to restyle the debug page. And the class is HtmlErrorRenderer, which the tree places under the ErrorRenderer directory, yet the snippet uses it with no use statement, while the three imports above cover only Debug, ErrorHandler and DebugClassLoader. Anyone copying the line has to add the import by hand. What the page does not say is where the default template comes from, what variables it receives, or whether a missing template file is reported at all.

Issues and pull requests go to the monorepo, not to this repository

The Resources section sends every contribution away from this checkout. Contributing points at symfony.com/doc/current/contributing/index.html, and the issue report and pull request links both target the main Symfony repository, with the text saying to do it in the main Symfony repository. That is the signature of a component split out of a monorepo: what lives here is the component's own source, its Tests directory with a phpunit.xml.dist beside it, composer.json, CHANGELOG.md, LICENSE and the README, while the working history lives elsewhere. A local patch here will not be merged by opening a pull request against this remote. The two funding links point at symfony.com/backers and symfony.com/sponsor, and the package states it is looking for a backer, which is the other piece of context this short page offers about itself.

The default branch is 8.2 and the newest 8.x tag is 8.1.8

The branch and the release list do not match. The default branch is named 8.2, so it is the development line for a release that has not been tagged in the three most recent releases. Those three are v8.1.8, v7.4.20 and v6.4.47, and all three carry the same date and nearly the same timestamp, 2026-09-29, minutes apart from each other. That pattern is three maintained branches cut on one day, which is what a component with a stable release cadence looks like. The last push recorded for the repository is 2026-09-22, four days before those tags, which is consistent with tags landing on the maintenance branches rather than on 8.2 itself. The practical consequence for a consumer: pinning to the default branch gets you unreleased 8.2 work, and pinning to v8.1.8 gets you the newest tagged 8.x line.

The page gives one composer command and no version requirement

Installation is a single line.

bash
composer require symfony/error-handler

That is the only command on the page, and there is no second form, no phar, no source checkout instruction and no note about a specific application layout. The package requires PHP to run, and the tree contains a composer.json, but the visible page prints no PHP constraint, no conflict list and no autoload section, so the version floor for this component is something you read out of the manifest in your own clone rather than out of this text. The same gap applies to the test setup: phpunit.xml.dist sits at the root of the tree next to Tests, and the page gives no command to run it, no fixture list and no testing dependency note.

Editorial conclusion

Reach for this when you are working on plain PHP outside a full framework stack and want error to exception conversion and a debug front end without assembling them yourself, and skip it if you expected configuration knobs: the visible page names no environment variable, no service definition and no PHP version requirement. Three things to check in your own clone first. The composer.json in the tree is where the version constraint lives, and it is not printed on the page. Branch and tag do not line up, because the default branch is 8.2 while the newest 8.x tag listed is v8.1.8. And any change you want to contribute belongs in the main Symfony repository, since the Resources section routes both issues and pull requests there.

Frequently asked questions

What does Debug::enable() in symfony/error-handler turn on?

It is the combined switch. The snippet shows ErrorHandler::register() and DebugClassLoader::enable() directly underneath it as commented alternatives under the comment or enable only one feature, so each piece can be enabled on its own, and both classes are imported at the top of that snippet.

Where do I report a bug in symfony/error-handler?

In the main Symfony repository. The Resources section links issue reports to github.com/symfony/symfony/issues and pull requests to github.com/symfony/symfony/pulls, and says to do both in the main Symfony repository, with the contributing guide at symfony.com/doc/current/contributing/index.html.

How do I install symfony/error-handler?

With one composer command, composer require symfony/error-handler. The visible page states no PHP version requirement, shows no configuration file or service definition, and does not print the contents of the composer.json that sits in the tree.

Can symfony/error-handler use a custom error page template?

Yes, through HtmlErrorRenderer::setTemplate with a path such as '/path/to/custom/error.html.php'. The snippet shows it commented out with the note that it applies when debug is not enabled, and the class sits under the ErrorRenderer directory in the tree while the snippet uses it without a use statement.

Which branch and release of symfony/error-handler is current?

The default branch is 8.2, while the newest 8.x release listed is v8.1.8. Three tags were published on the same day, 2026-09-29: v8.1.8, v7.4.20 and v6.4.47, and the last recorded push is dated 2026-09-22.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. symfony/error-handler on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/symfony-error-handler.svg)](https://hysenlabs.com/projects/symfony-error-handler)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/symfony-error-handler.svg)](https://hysenlabs.com/projects/symfony-error-handler)

Was this useful?