Today I ran into a problem where my PHP Application would throw this fatal error:
Fatal error: Exception thrown without a stack frame in Unknown on line 0
Which is so much fun, because it doesn’t have a line number, so I had no direction as to what exactly was causing the problem. Some quick googling came up with this website stating the following error:
Most often, the error will appear if you use an exception handler combined with an error reporting to exception handler by converting it to an ErrorException, then there a suddenly a whole new magnitude of ways to throw errors within the exception handle, especially if E_NOTICE, E_STRICT and/or E_WARNING errors are converted. This form most often occurs when you use variables without first initializing them. This error may be preventable by wrapping the exception handler within a try/catch block.
A second form of this error occurs when you attempt to throw an exception in a destructor. This is well documented in the PHP manual, but this can still be triggered if you accidentally throw an exception:
Manually – calling “throw new Exception(‘hello world’)’ in a destructor
Implicitly – calling a function that throws an exception (e.g. calling function foo() which throws an exception)
Error handler (ErrorException) – instating a user-defined function as an error handler which throws an ErrorException (which is still an error)
The problem was that the code I was working with wasn’t using a registered exception handler, nor a destructor. So I went through the controller I was working with and commented out each line, and one by one brought each line back. After a few minutes I found the problem: I had a class that would save itself to the Session, and that class also had a __sleep method which is invoked on serialization (see PHP manual). Because I hadn’t manually closed my php session with session_write_close() (PHP Manual), PHP would close the session when cleaning up & closing the request, which is executed outside of the stack. My __sleep() function had an error and would throw an exception, leading to the Fatal Error.
It was a little tricky to track down, but made complete sense once I found it.