Yakifo/amqtt

MQTTClient fails to raise appropriate exception if URI is broken

FabianElsmer opened this issue · 2 comments

A broken URI leads to the following exception when trying to connect to an MQTT broker:

Unhandled exception: 'NoneType' object has no attribute 'write'
paxexpress-api | Connection failed: AttributeError("'NoneType' object has no attribute 'write'")
paxexpress-api | Unhandled exception: 'NoneType' object has no attribute 'write'
paxexpress-api | Reconnection attempt failed: AttributeError("'NoneType' object has no attribute 'write'")
paxexpress-api | Unhandled exception: 'NoneType' object has no attribute 'write'
paxexpress-api | Reconnection attempt failed: AttributeError("'NoneType' object has no attribute 'write'")
paxexpress-api | Unhandled exception: 'NoneType' object has no attribute 'write'
paxexpress-api | Reconnection attempt failed: AttributeError("'NoneType' object has no attribute 'write'")
paxexpress-api | Maximum number of connection attempts reached. Reconnection aborted
paxexpress-api | ERROR:    Traceback (most recent call last):
paxexpress-api |   File "/opt/pysetup/.venv/lib/python3.8/site-packages/amqtt/client.py", line 165, in connect
paxexpress-api |     return await self._do_connect()
paxexpress-api |   File "/opt/pysetup/.venv/lib/python3.8/site-packages/amqtt/client.py", line 254, in _do_connect
paxexpress-api |     return_code = await self._connect_coro()
paxexpress-api |   File "/opt/pysetup/.venv/lib/python3.8/site-packages/amqtt/client.py", line 468, in _connect_coro
paxexpress-api |     return_code = await self._handler.mqtt_connect()
paxexpress-api |   File "/opt/pysetup/.venv/lib/python3.8/site-packages/amqtt/mqtt/protocol/client_handler.py", line 79, in mqtt_connect
paxexpress-api |     await self._send_packet(connect_packet)
paxexpress-api |   File "/opt/pysetup/.venv/lib/python3.8/site-packages/amqtt/mqtt/protocol/handler.py", line 543, in _send_packet
paxexpress-api |     await packet.to_stream(self.writer)
paxexpress-api |   File "/opt/pysetup/.venv/lib/python3.8/site-packages/amqtt/mqtt/packet.py", line 218, in to_stream
paxexpress-api |     writer.write(self.to_bytes())
paxexpress-api | AttributeError: 'NoneType' object has no attribute 'write'

Broken URI: mqtt://"user":"pass"@eu1.thethings.network"

Expectation: A descriptive exception should already be raised when creating the session and mention that no writer could be instantiated due to failing to properly parse the URI.

Hey, thanks for reporting. Unfortunately, I was not able to reproduce that. I added a test in test_client.py:

@pytest.mark.asyncio
async def test_connect_broken_uri():
    config = {"auto_reconnect": False}
    client = MQTTClient(config=config)
    await client.connect("mqtt://xxx:xxxx@eu1.thethings.network")

Which raises:

        except (ProtocolHandlerException, ConnectionError, OSError) as e:
            self.logger.warning("MQTT connection failed: %r" % e)
            self.session.transitions.disconnect()
>           raise ConnectException(e)
E           amqtt.client.ConnectException: [Errno 8] nodename nor servname provided, or not known

../amqtt/client.py:502: ConnectException

I also tried with await client.connect("mqtt://\"xxx\":xxxx@eu1.thethings.network"). Same effect. Can you provide a minimalistic example that reproduces the issue?

I played around with quotes and ended up reproducing the exception with:

@pytest.mark.asyncio
async def test_connect_broken_uri():
    config = {"auto_reconnect": False}
    client = MQTTClient(config=config)
    await client.connect('"mqtt://someplace')