Skip to content

[Messenger] messenger:failed:show fails with writeBuffer() exception #33049

@maks-rafalko

Description

@maks-rafalko

Symfony version(s) affected: 4.3.2

Description

When we run

bin/console messenger:failed:show 1 -vv

we get the following exception

Argument 1 passed to Symfony\Component\Console\Style\SymfonyStyle::writeBuffer() must be of the type string, null given, called

Exception trace:
 () at /app/vendor/symfony/console/Style/SymfonyStyle.php:384
 Symfony\Component\Console\Style\SymfonyStyle->writeBuffer() at /app/vendor/symfony/console/Style/SymfonyStyle.php:315
 Symfony\Component\Console\Style\SymfonyStyle->writeln() at /app/vendor/symfony/messenger/Command/AbstractFailedMessagesCommand.php:104
 Symfony\Component\Messenger\Command\AbstractFailedMessagesCommand->displaySingleMessage() at /app/vendor/symfony/messenger/Command/FailedMessagesShowCommand.php:121

The issue is in this line

$io->writeln(null === $flattenException ? '(no data)' : $flattenException->getTraceAsString());

Root of the issue is that $flattenException->getTraceAsString() returns null while string is expected.

Why does it return null?

Because when the RedeliveryStamp is being serialized from failed transport text message to the object, it is serializing FlattenException as well, but since there is no setter/modifier of this property, it is being skipped during serialization. It is not writable and PropertyAccessor fails.

How to reproduce

It's possible to reproduce creating a message in a failed queue with the following headers:

{
    "type": "App\\Message\\CreateUnbilledUsageCharge",
    "X-Message-Stamp-Symfony\\Component\\Messenger\\Stamp\\BusNameStamp": "[{\"busName\":\"messenger.bus.default\"}]",
    "X-Message-Stamp-Symfony\\Component\\Messenger\\Stamp\\SentToFailureTransportStamp": "[{\"originalReceiverName\":\"unbilled\"}]",
    "X-Message-Stamp-Symfony\\Component\\Messenger\\Stamp\\DelayStamp": "[{\"delay\":0}]",
    "X-Message-Stamp-Symfony\\Component\\Messenger\\Stamp\\RedeliveryStamp": "[{\"retryCount\":0,\"senderClassOrAlias\":\"failed\",\"exceptionMessage\":\"Failure Message.\",\"flattenException\":{\"statusCode\":500,\"headers\":[],\"class\":\"Core\\\\Exception\\\\LogicException\",\"file\":\"/app/src/MessageHandler/CreateUnbilledUsageChargeHandler.php\",\"line\":34,\"message\":\"Failure Message.\",\"code\":0,\"previous\":null,\"allPrevious\":[],\"trace\":[],\"traceAsString\":\"TRACE AS STRING\",\"asString\":\"AS STRING\"},\"redeliveredAt\":\"2019-08-07T06:06:57+00:00\"}]",
    "X-Message-Stamp-Symfony\\Component\\Messenger\\Stamp\\SentStamp": "[{\"senderClass\":\"Symfony\\\\Component\\\\Messenger\\\\Transport\\\\Doctrine\\\\DoctrineTransport\",\"senderAlias\":\"failed\"}]",
    "Content-Type": "application\/json"
}

Possible Solution

  1. Change the way how FlattenException is serialized.
  2. Cast $flattenException->getTraceAsString() to string like (string) $flattenException->getTraceAsString() but this is an ugly workaround

Additional context

This screenshot proofs there is a traceAsString before serialization:

debug1

(!) Upgrading to 4.3.3 does not solve the issue.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions