I am testing my error handling when calling Mqttnet's PublishAsync()
to a bad topic, such as "####", but I am getting unexpected behavior.
Expected:
I expected PublishAsync()
to return an MqttClientPublishResult
instance with ReasonCode
having value MqttClientPublishReasonCode.TopicNameInvalid
.
Actual: Instead, I am getting exception:
MQTTnet.Exceptions.MqttProtocolViolationException: 'The character '#' is not allowed in topics.
This is rather unfortunate, because using specific MqttClientPublishReasonCode
values from the MqttClientPublishResult
would help my error handling. Is there a way to receive this result object back without the method throwing an error?
I've tried instantiating my client using MqttClientOptionsBuilder
with its methods WithRequestProblemInformation()
and WithRequestResponseInformation()
, but the error still gets thrown. I know that a solution to this exists with PingAsync()
by calling TryPingAsync()
, but I cannot find a similar alternative for PublishAsync()
.
Section 3.3.2.1 of the MQTT v5 spec states:
The Topic Name in the PUBLISH packet MUST NOT contain wildcard characters [MQTT-3.3.2-2].
#
is a wildcard character, so your topic is not in accordance with the spec. When this happens the MQTT server should drop the network connection (with v5 you may get a "Malformed Packet" reason code).
PUBACK
reason code 144 ("Topic Name invalid"), which you mention in your question, is for when "The Topic Name is not malformed, but is not accepted by this Client or Server.". So it's not applicable in this case (as the topic is malformed).
The authors of MQTTNet had two main options, send the PUBLISH
(meaning the server drops the conneciton) or raise an exception. While sending the packet might be a valid approach it can cause confusing issues (e.g. a disconnect/reconnect loop when the packet is resent every time the connection comes up).
If you take a look here you can see the various exceptions thrown when the topic is invalid. Handling the MqttProtocolViolationException
exception should not complicate things too much, a better option may be to validate the config/user inputs to avoid the use of such topics in the first place.