The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue

Solution 1:

I spent hours trying understand why I was getting a MessageLockLostException. The reason for me was due to AutoComplete defaulting to true.

If you're going to call messsage.Complete() (or CompleteAsync()) then you should instantiate an OnMessageOptions object, set AutoComplete to false, and pass it into your OnMessage call.

var options = new OnMessageOptions();
options.AutoComplete = false;

client.OnMessage(processCalculations, options);

Solution 2:

I was having a similar issue. Messages were being handled successfully, but when they went to complete, the Service Bus didn't have a valid lock anymore. It turns out my TopicClient.PrefetchCount was too high.

It appears that the lock begins on all prefetched messages as soon as they are fetched. If your cumulative message processing time surpasses the lock timeout every other prefetched message will fail to complete. It will return to the service bus.

Solution 3:

It took me 2 days to resolve similar issue - same exception.
This exception may have multiple reasons, I'll describe couple of config options that may help you stranger...

ServiceBus Queue or Topic-subscription config:

  • Message lock duration on Queue / Topic subscription is too low set it to approx. message processing time

ServiceBusClient options config:

  • tryTimeout is too short, set it to ~10s for diagnostics

ServiceBusProcessor options config:

  • AutoCompleteMessages is by default set to true, set it to false
  • PrefetchCount is too high, for diagnostics set it to 0
  • ReceiveMode set it to ServiceBusReceiveMode.PeekLock
  • MaxConcurrentCalls for diagnostics set it to 1

After finding correct values (optimized for a given system) I no longer observed any issues.

Solution 4:

Instead of renewing the lock manualy, when you create the client subscription, try auto renewing it using the client's OnMessageOptions() like this:

        OnMessageOptions options = new OnMessageOptions();

        options.AutoRenewTimeout = TimeSpan.FromMinutes(1);

        try
        {
            client = Subscription.CreateClient();

            client.OnMessageAsync(MessageReceivedComplete, options);
        }
        catch (Exception ex)
        {
            throw new Exception (ex);
        }