Skip to content

Option WithAutoReconnectDelay fails to reconnect when unauthorized. #1810

@jechtom

Description

@jechtom

Authorization failure breaks the managed client and it will never try to reconnect.

This happens if I use ManagedMqttClient with the feature AutoReconnectDelay (tuned on by default) together with client option WithoutThrowOnNonSuccessfulConnectResponse (expected to be turned on by default in the future).

Which component is your bug related to?

  • Client (4.2.1.781, latest on 2023-08-06)
  • ManagedClient (4.2.1.781, latest on 2023-08-06)

To Reproduce

Steps to reproduce the behavior:

  1. Have any MQTT server that requires authentication.
  2. Use (currently latest) MQTTnet.Extensions.ManagedClient 4.2.1.781.
  3. Run this code:
            var mqttClientOptions = new ManagedMqttClientOptionsBuilder()
                //.WithAutoReconnectDelay(TimeSpan.FromSeconds(5)) <- no needed, turned on by default
                .WithClientOptions(b => b
                    .WithCredentials("aaaaaaaaaa invalid credentials")
                    .WithoutThrowOnNonSuccessfulConnectResponse() // will be enabled by default in the future versions
                    .WithConnectionUri("wss://address-of-you-mqtt-server")
                ).Build();

            var mqttClient = new MqttFactory().CreateManagedMqttClient();
            await mqttClient.StartAsync(mqttClientOptions).ConfigureAwait(false);
            await Task.Delay(Timeout.Infinite);
  1. Run the code.
  2. Client will contact the server only once and will not retry.

Expected behavior

The client should try to reconnect in regular intervals (5s by default).
Instead if will internally fail on error:

Not allowed to connect while connect/disconnect is pending.

Full code example with logging

Full code:

using MQTTnet.Extensions.ManagedClient;
using MQTTnet;
using System.Diagnostics;

namespace MqttReconnectTest
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            Stopwatch sw = Stopwatch.StartNew();

            Task Print(string text)
            {
                Console.WriteLine($"[{sw.Elapsed:s\\.fff}s] {text}");
                return Task.CompletedTask;
            }

            await Print("Starting.");

            var mqttClientOptions = new ManagedMqttClientOptionsBuilder()
                //.WithAutoReconnectDelay(TimeSpan.FromSeconds(5)) <- no e, turned on by default
                .WithClientOptions(b => b
                    .WithCredentials("aaaaaaaaaa invalid credentials")
                    .WithoutThrowOnNonSuccessfulConnectResponse() // will be enabled by default in the future versions
                    .WithConnectionUri("wss://localhost:6001/servicebus")
                ).Build();

            var mqttClient = new MqttFactory().CreateManagedMqttClient();

         
            mqttClient.ConnectedAsync += (t) => Print("ConnectedAsync.");
            mqttClient.ConnectingFailedAsync += (t) => Print($"ConnectingFailedAsync: {t.Exception}");
            mqttClient.ConnectionStateChangedAsync += (t) => Print("ConnectionStateChangedAsync.");
            mqttClient.DisconnectedAsync += (t) => Print("DisconnectedAsync.");

            await mqttClient.StartAsync(mqttClientOptions).ConfigureAwait(false);

            await Task.Delay(Timeout.Infinite);
        }
    }
}

Output:

[0.000s] Starting.
[0.209s] ConnectingFailedAsync: MQTTnet.Exceptions.MqttCommunicationException: Client connected but server denied connection with reason 'NotAuthorized'.
   at MQTTnet.Extensions.ManagedClient.ManagedMqttClient.ReconnectIfRequiredAsync(CancellationToken cancellationToken)
[5.217s] ConnectingFailedAsync: System.InvalidOperationException: Not allowed to connect while connect/disconnect is pending.
   at MQTTnet.Client.MqttClient.ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnet.Extensions.ManagedClient.ManagedMqttClient.ReconnectIfRequiredAsync(CancellationToken cancellationToken)
[10.230s] ConnectingFailedAsync: System.InvalidOperationException: Not allowed to connect while connect/disconnect is pending.
   at MQTTnet.Client.MqttClient.ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnet.Extensions.ManagedClient.ManagedMqttClient.ReconnectIfRequiredAsync(CancellationToken cancellationToken)
[15.241s] ConnectingFailedAsync: System.InvalidOperationException: Not allowed to connect while connect/disconnect is pending.
   at MQTTnet.Client.MqttClient.ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnet.Extensions.ManagedClient.ManagedMqttClient.ReconnectIfRequiredAsync(CancellationToken cancellationToken)
[20.243s] ConnectingFailedAsync: System.InvalidOperationException: Not allowed to connect while connect/disconnect is pending.
   at MQTTnet.Client.MqttClient.ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnet.Extensions.ManagedClient.ManagedMqttClient.ReconnectIfRequiredAsync(CancellationToken cancellationToken)
..........

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions