-
Notifications
You must be signed in to change notification settings - Fork 26
Closed
Labels
Description
Hi, I've noticed that sometimes when I replay previously dead-lettered messages, an exception is thrown from Rebus, preventing further messages from being processed.
It looks like BuiltInDeadletteringErrorHandler sends the existing message headers along with a new error message and description, however if that message already had error headers, then there can be a conflict in error messages, which Azure's library will throw an exception for.
Exception that's being thrown:
System.InvalidOperationException: Differing deadletter reasons cannot be specified for both the 'propertiesToModify' and 'deadLetterReason' parameters. The values should either be identical or only be specified in one of the parameters.
at Azure.Messaging.ServiceBus.ServiceBusReceiver.DeadLetterMessageAsync(ServiceBusReceivedMessage message, IDictionary`2 propertiesToModify, String deadLetterReason, String deadLetterErrorDescription, CancellationToken cancellationToken)
at Rebus.Config.AdditionalAzureServiceBusConfigurationExtensions.BuiltInDeadletteringErrorHandler.HandlePoisonMessage(TransportMessage transportMessage, ITransactionContext transactionContext, ExceptionInfo exception)
at Rebus.Retry.Simple.DefaultRetryStep.PassToErrorHandler(StepContext context, ExceptionInfo exception)
at Rebus.Retry.Simple.DefaultRetryStep.HandleException(Exception exception, ITransactionContext transactionContext, String messageId, IncomingStepContext context, Func`1 next)
at Rebus.Retry.Simple.DefaultRetryStep.Process(IncomingStepContext context, Func`1 next)
at Rebus.Workers.ThreadPoolBased.ThreadPoolWorker.ProcessMessage(TransactionContext context, TransportMessage transportMessage)
I think a straightforward way to prevent this in BuiltInDeadletteringErrorHandler would be to remove existing error headers if they exist. I can create a PR if that seems like a good solution.
transportMessage.Headers.Remove("DeadLetterReason");
transportMessage.Headers.Remove("DeadLetterErrorDescription");
_log.Error("Dead-lettering message with ID {messageId}, reason={deadLetterReason}, exception info: {exceptionInfo}",
messageId, deadLetterReason, exception);
await messageReceiver.DeadLetterMessageAsync(message, transportMessage.Headers.ToDictionary(k => k.Key, v => (object)v.Value), deadLetterReason, deadLetterErrorDescription);
Thanks!