Customizing Error Handling

Component: NServiceBus
NuGet Package NServiceBus (6.x)

The IManageMessageFailures interface has been deprecated. Instead, the same functionality can be achieved by adding a new behavior which is invoked during the message processing pipeline. Read this article on how to manipulate the pipeline with behaviors.

Create a new behavior

Implement a new behavior, which extends the ITransportReceiveContext context. This context provides details about the message at the transport level. Calling next() in the pipeline will invoke the subsequent pipeline processing steps.

class CustomErrorHandlingBehavior :
    Behavior<ITransportReceiveContext>
{
    public override Task Invoke(ITransportReceiveContext context, Func<Task> next)
    {
        return next();
    }
}

Handling Deserialization Errors

To handle any deserialization errors, wrap the next() operation in a try-catch block and handle the MessageDeserializationException as shown:

try
{
    await next()
        .ConfigureAwait(false);
}
catch (MessageDeserializationException deserializationException)
{
    // Custom processing that needs to occur when a serialization failure occurs.
    log.Error("Message deserialization failed", deserializationException);
    throw;
}

Handling Other Errors

To handle any other errors, wrap the next() operation in a try-catch block and handle the Exception as shown:

try
{
    await next()
        .ConfigureAwait(false);
}
catch (Exception exception)
{
    // Custom processing that need to occur when a message always fails.
    log.Error("Message processing failed", exception);
    throw;
}
Throwing the exception in the catch block will forward the message to the error queue. If that's not desired, remove the throw from the catch block to indicate that the message has been successfully processed.

Rolling Back

To rollback the receive operation, instead of either handling the message or to forward it to the error queue, invoke AbortReceiveOperation as shown below:

try
{
    await next()
        .ConfigureAwait(false);
}
catch (Exception)
{
    // Custom processing that need to occur when a message always fails.
    // To rollback the receive operation instead of mark as processed:
    context.AbortReceiveOperation();
}

Registering the Behavior

In the example below, the new behavior CustomErrorHandlingBehavior is registered to be part of the message handling pipeline. This new behavior is registered such that it will be invoked after NServiceBus has invoked the recoverability mechanism. This includes Second-Level Retries if they are enabled.

class NewMessageProcessingPipelineStep :
    RegisterStep
{
    public NewMessageProcessingPipelineStep()
        : base(
            stepId: "CustomErrorHandlingBehavior",
            behavior: typeof(CustomErrorHandlingBehavior),
            description: "Adds custom error behavior to pipeline")
    {
        // Within a stage it is sometimes necessary to configure a specific
        // step order. This can be achieved by invoking on of the following methods:
        //  - InsertAfter,
        //  - InsertAfterIfExists,
        //  - InsertBefore,
        //  - InsertBeforeIfExists
    }
}

Related Articles


Last modified