Particular.LicensingComponent.BrokerThroughput.BrokerThroughputCollectorHostedService|Failed to gather throughput from broker|System.Text.Json.JsonException: Unknown queue type: rabbit_mqtt_qos0_queue
Anyone generating a usage report in ServiceControl with a RabbitMQ server that has the MQTT Plugin enabled and uses MQTT QoS 0 queues.
Original bug report
Describe the bug
Description
ServiceControl usage tool throws an exception when scanning the queues with mqtt qos0 queue types. The error is thrown by the transport queue type converter.
Expected behavior
Usage tool skips those queue types and does not fail.
Actual behavior
An exception is thrown and the usage functionality does not complete.
Versions
Please list the version of the relevant packages or applications in which the bug exists.
- ServiceControl 6.7.1, most likely in all versions that support collecting usage data.
Steps to reproduce
- Create a queue in the RabbitMQ broker that uses an unsupported queue type.
- Run the usage tool in ServiceControl
- Check log files for the exception above.
Relevant log output
2025-08-06 13:41:25.5385|00:01:09.798|56|Error|Particular.LicensingComponent.BrokerThroughput.BrokerThroughputCollectorHostedService|Failed to gather throughput from broker|System.Text.Json.JsonException: Unknown queue type: rabbit_mqtt_qos0_queue
at NServiceBus.Transport.RabbitMQ.ManagementApi.QueueTypeConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options) in /_/src/NServiceBus.Transport.RabbitMQ/Administration/ManagementApi/Converters/QueueTypeConverter.cs:line 20
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)
at System.Net.Http.Json.HttpClientJsonExtensions.<FromJsonAsyncCore>g__Core|12_0[TValue,TJsonOptions](HttpClient client, Task`1 responseTask, Boolean usingResponseHeadersRead, CancellationTokenSource linkedCTS, Func`4 deserializeMethod, TJsonOptions jsonOptions, CancellationToken cancellationToken)
at NServiceBus.Transport.RabbitMQ.ManagementApi.ManagementClient.Get[T](String url, CancellationToken cancellationToken)
at NServiceBus.Transport.RabbitMQ.ManagementApi.ManagementClient.GetQueues(Int32 page, Int32 pageSize, CancellationToken cancellationToken) in /_/src/NServiceBus.Transport.RabbitMQ/Administration/ManagementApi/ManagementClient.cs:line 127
at ServiceControl.Transports.RabbitMQ.RabbitMQQuery.<>c__DisplayClass5_0.<<GetQueueNames>b__0>d.MoveNext() in /_/src/ServiceControl.Transports.RabbitMQ/RabbitMQQuery.cs:line 78
--- End of stack trace from previous location ---
at Polly.ResiliencePipeline.<>c__10`1.<<ExecuteAsync>b__10_0>d.MoveNext()
--- End of stack trace from previous location ---
at Polly.Outcome`1.GetResultOrRethrow()
at Polly.ResiliencePipeline.ExecuteAsync[TResult](Func`2 callback, CancellationToken cancellationToken)
at ServiceControl.Transports.RabbitMQ.RabbitMQQuery.GetQueueNames(CancellationToken cancellationToken)+MoveNext() in /_/src/ServiceControl.Transports.RabbitMQ/RabbitMQQuery.cs:line 78
at ServiceControl.Transports.RabbitMQ.RabbitMQQuery.GetQueueNames(CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
at Particular.LicensingComponent.BrokerThroughput.BrokerThroughputCollectorHostedService.GatherThroughput(CancellationToken stoppingToken) in /_/src/Particular.LicensingComponent/BrokerThroughput/BrokerThroughputCollectorHostedService.cs:line 69
at Particular.LicensingComponent.BrokerThroughput.BrokerThroughputCollectorHostedService.GatherThroughput(CancellationToken stoppingToken) in /_/src/Particular.LicensingComponent/BrokerThroughput/BrokerThroughputCollectorHostedService.cs:line 69
at Particular.LicensingComponent.BrokerThroughput.BrokerThroughputCollectorHostedService.ExecuteAsync(CancellationToken stoppingToken) in /_/src/Particular.LicensingComponent/BrokerThroughput/BrokerThroughputCollectorHostedService.cs:line 48
Additional Information
Workarounds
Possible solutions
Update the queue type parser to handle all RabbitMQ queue types gracefully.
Additional information
The QueueTypeConverter System.Text.Json converter throws an exception if a queue type that is not hard coded in the switch statement is indicated in the JSON.
https://github.com/Particular/NServiceBus.RabbitMQ/blob/master/src/NServiceBus.Transport.RabbitMQ/Administration/ManagementApi/Converters/QueueTypeConverter.cs#L15-L20
This converter is triggered during the ManagementClient.GetQueues method call when deserializing the response:
https://github.com/Particular/NServiceBus.RabbitMQ/blob/master/src/NServiceBus.Transport.RabbitMQ/Administration/ManagementApi/ManagementClient.cs#L121
The ServiceControl.Transport.RabbitMQ library calls the ManagementClient.GetQueues method:
https://github.com/Particular/ServiceControl/blob/master/src/ServiceControl.Transports.RabbitMQ/RabbitMQQuery.cs#L78
[!NOTE]
The ManagementClient class is accessed via internals visible to by the ServiceControl.Transport.RabbitMQ library.
Symptoms
The following error appears in the ServiceControl log:
Who's affected
Anyone generating a usage report in ServiceControl with a RabbitMQ server that has the MQTT Plugin enabled and uses MQTT QoS 0 queues.
Root cause
Confirmed workarounds
Original bug report
Describe the bug
Description
ServiceControl usage tool throws an exception when scanning the queues with mqtt qos0 queue types. The error is thrown by the transport queue type converter.
Expected behavior
Usage tool skips those queue types and does not fail.
Actual behavior
An exception is thrown and the usage functionality does not complete.
Versions
Please list the version of the relevant packages or applications in which the bug exists.
Steps to reproduce
Relevant log output
Additional Information
Workarounds
Possible solutions
Update the queue type parser to handle all RabbitMQ queue types gracefully.
Additional information
The
QueueTypeConverterSystem.Text.Json converter throws an exception if a queue type that is not hard coded in the switch statement is indicated in the JSON.https://github.com/Particular/NServiceBus.RabbitMQ/blob/master/src/NServiceBus.Transport.RabbitMQ/Administration/ManagementApi/Converters/QueueTypeConverter.cs#L15-L20
This converter is triggered during the
ManagementClient.GetQueuesmethod call when deserializing the response:https://github.com/Particular/NServiceBus.RabbitMQ/blob/master/src/NServiceBus.Transport.RabbitMQ/Administration/ManagementApi/ManagementClient.cs#L121
The
ServiceControl.Transport.RabbitMQlibrary calls theManagementClient.GetQueuesmethod:https://github.com/Particular/ServiceControl/blob/master/src/ServiceControl.Transports.RabbitMQ/RabbitMQQuery.cs#L78
Backported to