Skip to content

Azure Service Bus batching fails with mixed session IDs, causes stuck messages with outbox pattern #2000

@AcnolgenIndustries

Description

@AcnolgenIndustries

Describe the bug
When partitioning is enabled for an event queue in Azure Service Bus using the outbox pattern, messages can get stuck due to the way batching is handled in AzureServiceBusSenderProtocol. Azure Service Bus does not support sending a batch of messages that have different session IDs. As a result, batches containing messages with different session IDs are not processed as expected, leading to certain messages getting stuck and never being sent.

To Reproduce

  1. Enable sessions on an Azure Service Bus event queue.
  2. Publish multiple messages using the outbox pattern where messages have different session IDs.
  3. When the sender attempts to batch and send the messages, some messages with session IDs different from the first in the batch may get stuck or never be sent, as batching to different session IDs is not supported by Azure Service Bus.

Expected behavior
The sender should correctly batch messages by their session ID without mixing session IDs in a single batch. Specifically, batching should be grouped such that consecutive messages with the same session ID are batched together. For example, if message 1 and 2 have session ID 'A', message 3 has session ID 'B', and message 4 returns to session ID 'A', three batches should be sent in order: [1,2], [3], [4].

Original Error Message & Stack Trace
This error occurs when a batch contains distinct SessionId/PartitionKey values and partitioning is enabled:

Batching brokered messages with distinct SessionId or PartitionKey is not supported for an entity with partitioning enabled.LogicalPartitionId:16::PartitionKey:4e273b69-faed-48db-b9c5-3c2179107880::SessionId:4e273b69-faed-48db-b9c5-3c2179107880::MessageId:08de4979-0c00-233e-4696-01abe3290000::ViaPartitionKey::: Reference:0d118343-f047-43d9-9569-ee08370f79d6, TrackingId: 065dbbd70000001c0310951369575f58_G3_B35, SystemTracker:gi::G3:Send: 241266541:638635232918930000:RootManageSharedAccessKey:NamespaceSAS:F15:C28, bi::link51418387(659587705_G3), Timestamp:2026-01-02T06:03:46
For troubleshooting information, see https://aka.ms/azsdk/net/servicebus/exceptions/troubleshoot.

System. InvalidOperationException: Batching brokered messages with distinct SessionId or PartitionKey is not supported for an entity with partitioning enabled.LogicalPartitionId:16::PartitionKey:4e273b69-faed-48db-b9c5-3c2179107880::SessionId:4e273b69-faed-48db-b9c5-3c2179107880::MessageId:08de4979-0c00-233e-4696-01abe3290000::ViaPartitionKey: :: Reference:0d118343-f047-43d9-9569-ee08370f79d6, TrackingId:065dbbd70000001c0310951369575f58_G3_B35, SystemTracker: gi::G3:Send:241266541:638635232918930000:RootManageSharedAccessKey:NamespaceSAS:F15:C28, bi::link51418387(659587705_G3), Timestamp:2026-01-02T06:03:46
For troubleshooting information, see https://aka.ms/azsdk/net/servicebus/exceptions/troubleshoot.
   at Azure. Messaging.ServiceBus. Amqp.AmqpSender.SendBatchInternalAsync(AmqpMessage batchMessage, TimeSpan timeout, CancellationToken cancellationToken)
   at Azure.Messaging. ServiceBus.Amqp.AmqpSender.SendBatchInternalAsync(AmqpMessage batchMessage, TimeSpan timeout, CancellationToken cancellationToken)
   at Azure.Messaging.ServiceBus.Amqp.AmqpSender.SendBatchInternalAsync(IReadOnlyCollection`1 messages, TimeSpan timeout, CancellationToken cancellationToken)
   at Azure.Messaging.ServiceBus. Amqp.AmqpSender.<>c.<<SendBatchAsync>b__29_0>d.MoveNext()
--- End of stack trace from previous location ---
   at Azure. Messaging.ServiceBus.ServiceBusRetryPolicy.<>c__23`1.<<RunOperation>b__23_0>d.MoveNext()
--- End of stack trace from previous location ---
   at Azure.Messaging. ServiceBus.ServiceBusRetryPolicy.RunOperation[T1,TResult](Func`4 operation, T1 t1, TransportConnectionScope scope, CancellationToken cancellationToken, Boolean logTimeoutRetriesAsVerbose)
   at Azure.Messaging.ServiceBus.ServiceBusRetryPolicy. RunOperation[T1,TResult](Func`4 operation, T1 t1, TransportConnectionScope scope, CancellationToken cancellationToken, Boolean logTimeoutRetriesAsVerbose)
   at Azure.Messaging.ServiceBus.ServiceBusRetryPolicy.RunOperation[T1](Func`4 operation, T1 t1, TransportConnectionScope scope, CancellationToken cancellationToken)
   at Azure.Messaging. ServiceBus.Amqp.AmqpSender.SendBatchAsync(ServiceBusMessageBatch messageBatch, CancellationToken cancellationToken)
   at Azure.Messaging. ServiceBus.ServiceBusSender.SendMessagesAsync(ServiceBusMessageBatch messageBatch, CancellationToken cancellationToken)
   at Wolverine.AzureServiceBus.Internal.AzureServiceBusSenderProtocol.SendBatchAsync(ISenderCallback callback, OutgoingMessageBatch batch) in /home/runner/work/wolverine/wolverine/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusSenderProtocol. cs:line 70

Additional context

  • Existing logic in AzureServiceBusSenderProtocol.SendBatchAsync() does not distinguish session IDs when batching messages, which leads to this problem.
  • The solution should ensure ordering is preserved and logic remains as intended, but batches must only include consecutive messages with the same session ID.
  • Reference file: src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusSenderProtocol.cs

This is likely to impact any user leveraging sessions with the outbox pattern and Azure Service Bus transport in Wolverine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions