Description
Symfony version(s) affected: 5.2.3
Description
The $previous
property of FlattenException
is not documented as nullable, and it denormalizes incorrectly when set to null
.
How to reproduce
$fe = FlattenException::create(new \Exception());
dump($fe->getPrevious());
$sfe = $this->serializer->serialize($fe, 'json');
$dfe = $this->serializer->deserialize($sfe, FlattenException::class, 'json');
dump($dfe->getPrevious());
Output:
^ null
^ Symfony\Component\ErrorHandler\Exception\FlattenException^ {#1272
-message: null
-code: null
-previous: null
-trace: null
-traceAsString: null
-class: null
-statusCode: null
-statusText: null
-headers: null
-file: null
-line: null
-asString: null
}
Possible Solution
Super simple - just adding a PHPDoc for the property:
/** @var FlattenException|null */
private $previous;
then executing the same code as above returns:
^ null
^ null
Additional context
This was found out when using consuming Pub/Sub messages with symfony/messenger
and sroze/messenger-enqueue-transport
, which use FlattenException
for ErrorDetailsStamp
.
When the message handler fails processing the message for the very first time, it adds ErrorDetailsStamp
with exception flattened (and "previous": null
).
On first retry, the stamp is deserialized, and what originally was
"flattenException": {
"previous": null,
turns into
-flattenException: Symfony\Component\ErrorHandler\Exception\FlattenException^ {#1912
-previous: Symfony\Component\ErrorHandler\Exception\FlattenException^ {#1900
-message: null
-code: null
-previous: null
-trace: null
-traceAsString: null
-class: null
-statusCode: null
-statusText: null
-headers: null
-file: null
-line: null
-asString: null
}
(This is our issue right here.)
Finally, when processing fails again, the ErrorDetailsStamp
(with all the above null
s) fails deserialization with the following errors:
In Serializer.php line 122:
Could not decode stamp: The type of the "message" attribute for class "Symfony\Component\ErrorHandler\Exception\FlattenException" must be one of "string" ("null" given).
In AbstractObjectNormalizer.php line 494:
The type of the "message" attribute for class "Symfony\Component\ErrorHandler\Exception\FlattenException" must be one of "string" ("null" given).
Which means retrying to handle the message works fine as long as max_retries
is set to 1
, but fails if it's anything above this.
Adding mentioned PHPDoc makes it work perfectly fine.