September 14, 2017 Javier Eguiluz

Designing exception messages is hard because they are mostly used in stressful situations. Their contents must achieve a delicate balance between giving enough information to find out the exception cause, and not giving too much information that could confuse or stress the user even more.

In Symfony 3.3 we redesigned the web exceptions and in Symfony 3.4, we'll do the same with the console exceptions. The main problem of the original exceptions is that they focus on explaining what happened, ignoring where the exception happened. For example, consider this Symfony console exception:

1 2 [Symfony\Component\Debug\Exception\ContextErrorException] Notice: Undefined variable: b

The problem is well explained and the exact exception class is included too, but where did this error happen? Which file and line should you look into to fix it? If you run the command in a more verbose mode you'll see the exact file and line, but that usually means running the command again with the -v option.

Repeating the execution of a command is not always possible or convenient: maybe the error happens after 10 minutes of executing a long-running command, or only occurs the first time is executed before it changes some information in the database, or is run unattended in a Cron task.

Now take a look at the same exception as displayed by Symfony 3.4:

1 2 In CacheClearCommand.php line 88: Notice: Undefined variable: b

Console exceptions now always display the exact file and line where the error occurred, no matter what is the command verbosity. Moreover, the exception class is no longer displayed by default, because it's not that useful most of the times. The exception class is displayed when running the command in verbose mode.

The only exception to this new behavior are the internal exceptions of the Symfony Console component. Showing the file and line number is not useful in those cases because that's something out of your responsibility and that you cannot change. So, instead of this:

1 2 3 4 In Application.php line 615: Command "foo" is not defined. Did you mean this? app:foo

You will keep seeing internal exceptions like this: