Question

I have a custom Exception handler in my code (which used to work properly), until suddenly I saw this error yesterday:

PHP Fatal error:  Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /raid0/nginx/www/voiceportal/lib/logutils.php:34 Stack trace:
#0 /raid0/nginx/www/voiceportal/lib/logutils.php(34): serialize(Array)
#1 [internal function]: custom_exception_handler(Object(AMQPConnectionException))
#2 {main}

I read that it can be caused if an anonymous function is tried to be serialized, but this is what threw the error for me:

//logutils.php
function custom_exception_handler($exception) {
   $trace_id = uniqid();
   $trace = serialize(array('trace_id' => $trace_id, 'trace' => $exception->getTrace()));
   ...
}

Not sure if it was caused by trying to serialize getTrace(), but if I remember correctly, it used to work earlier.

The original exception was (as seen in the trace) AMQPConnectionException.

I am trying to understand what caused the 'Serialization of Closure not allowed' exception.

Thanks!

Was it helpful?

Solution

PHP's backtrace structure includes a reference to the object whose method is being called at each level of the stack. When it tries to serialize the trace, any objects which reference closures (or reference objects which themselves reference closures and so on) will prevent serialization.

In your case, you can re-cast the trace into a slightly less descriptive form or find which objects contain closures and either repackage the closures as __invoke instances or skip them when serializing by implementing Serializable, as described here. Your choice here would depend on what you're doing with the trace. If it's only meant to a be human-readable description of what went wrong, consider using the getTraceAsString() method instead of getTrace().

OTHER TIPS

I've written a function that allows any Exception to be serialized. This is done by flattening complex values in the backtrace.

Source:

https://gist.github.com/Thinkscape/805ba8b91cdce6bcaf7c

Usage:

//logutils.php
function custom_exception_handler($exception) {
   flattenExceptionBacktrace($exception); // <---- ADD THIS
   $trace_id = uniqid();
   $trace = serialize(array('trace_id' => $trace_id, 'trace' => $exception->getTrace()));
   ...
}

I know this is old topic, but I would like to recommend my own library to serializing stack traces. Object $stackTrace can contain values and can be serialized. Unserialized object will contain only custom dumps of variables (@see interface).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top