{"record":{"id":"f86214725a354ce7","repo":"locustio/locust","slug":"invalid-timeout","errorCode":null,"errorMessage":"Invalid timeout.","messagePattern":"Invalid timeout\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"locust/contrib/mqtt.py","lineNumber":345,"sourceCode":"        reasoncode: ReasonCode,\n        properties: Properties | None,\n    ) -> None:\n        self._on_connect_cb(client, userdata, {}, reasoncode)\n\n    def _loop(self, timeout: float = 1.0) -> MQTTErrorCode:\n        \"\"\"Override the parent's _loop method to optionally use selectors.\n\n        When use_loop_selectors is True, this uses a selector-based implementation that allows more than 340 connections.\n        Otherwise, it falls back to the parent's implementation.\n        \"\"\"\n        if self._use_loop_selectors:\n            return self._loop_selectors(timeout)\n        else:\n            return super()._loop(timeout)\n\n    def _loop_selectors(self, timeout: float = 1.0) -> MQTTErrorCode:\n        if timeout < 0.0:\n            raise ValueError(\"Invalid timeout.\")\n\n        sel = selectors.DefaultSelector()\n\n        eventmask = selectors.EVENT_READ\n\n        with suppress(IndexError):\n            packet = self._out_packet.popleft()\n            self._out_packet.appendleft(packet)\n            eventmask = selectors.EVENT_WRITE | eventmask\n\n        # used to check if there are any bytes left in the (SSL) socket\n        pending_bytes = 0\n        if hasattr(self._sock, \"pending\"):\n            pending_bytes = self._sock.pending()  # type: ignore\n\n        # if bytes are pending do not wait in select\n        if pending_bytes > 0:\n            timeout = 0.0","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/locustio/locust/blob/f391a716e12c2c712e80b5835e877b7933397453/locust/contrib/mqtt.py#L327-L363","documentation":"The MQTT client's selector-based network loop (_loop_selectors) raises ValueError when the given timeout is negative, since selectors cannot wait for a negative duration. This is a defensive check inside the custom gevent-compatible loop of locust's MQTT contrib client.","triggerScenarios":"Constructing or configuring the MQTT user/client such that the loop timeout resolves below 0.0 (e.g. keepalive or timeout math yielding a negative value) while the selectors-based loop path is active.","commonSituations":"Custom timeout configuration in a Milvus/MQTT locustfile; clock/deadline calculations passing past deadlines as negative timeouts; subclass overriding _loop and passing a bad timeout.","solutions":["Ensure the timeout value passed into the loop is >= 0.0","Clamp the computed timeout: timeout = max(0.0, timeout)","Check keepalive/timeout settings on the MQTT client configuration"],"exampleFix":"// before\nclient.loop(timeout=computed_deadline - now)  # may be negative\n// after\ntimeout = max(0.0, computed_deadline - now)\nclient.loop(timeout=timeout)","handlingStrategy":"validation","validationCode":"timeout = max(0.0, timeout)\nassert timeout >= 0.0, f\"MQTT loop timeout must be non-negative, got {timeout}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp computed timeouts to >= 0 before passing to the loop","Avoid passing absolute deadlines where relative durations are expected","Test MQTT users with short runs to surface loop configuration errors early"],"tags":["python","mqtt","valueerror","configuration"],"backgroundTag":"invalid-timeout","analyzedSha":"f391a716e12c2c712e80b5835e877b7933397453","analyzedAt":"2026-08-29T00:36:13.872Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}