From 706d1c7ea28ad852aadc48c4c3d1ae9def669b07 Mon Sep 17 00:00:00 2001 From: agessaman Date: Thu, 25 Jun 2026 08:13:55 -0700 Subject: [PATCH] fix(mqtt): enhance error handling for connection refusals Improved error handling in the MQTT client to log specific reasons for connection refusals, including detailed return codes. This change ensures that users are informed of authentication issues and server availability problems, enhancing the debugging experience. --- .../src/PsychicMqttClient.cpp | 33 +++++++++++++------ src/helpers/bridges/MQTTBridge.cpp | 9 ++++- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/PsychicMqttClient/src/PsychicMqttClient.cpp b/lib/PsychicMqttClient/src/PsychicMqttClient.cpp index 1f94ad82..c91f3a50 100644 --- a/lib/PsychicMqttClient/src/PsychicMqttClient.cpp +++ b/lib/PsychicMqttClient/src/PsychicMqttClient.cpp @@ -726,17 +726,30 @@ void PsychicMqttClient::_onPublish(esp_mqtt_event_handle_t &event) void PsychicMqttClient::_onError(esp_mqtt_event_handle_t &event) { ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) - { - log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err); - log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err); - log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno); - ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno)); + esp_mqtt_error_codes_t *err = event->error_handle; - for (uint8_t i = 0; i < _onErrorUserCallbackCount; ++i) - { - _onErrorUserCallbacks[i](*event->error_handle); - } + if (err->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) + { + log_error_if_nonzero("reported from esp-tls", err->esp_tls_last_esp_err); + log_error_if_nonzero("reported from tls stack", err->esp_tls_stack_err); + log_error_if_nonzero("captured as transport's socket errno", err->esp_transport_sock_errno); + ESP_LOGI(TAG, "Last errno string (%s)", strerror(err->esp_transport_sock_errno)); + } + else if (err->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) + { + // Broker accepted the socket but rejected the MQTT CONNECT. The return + // code distinguishes auth failures (4=bad user/pass, 5=not authorized) + // from server unavailable (3), protocol mismatch (1), and client-id + // rejection (2) — the key signal for diagnosing a server-side lockout. + ESP_LOGE(TAG, "Connection refused, return code 0x%x", err->connect_return_code); + } + + // Forward every error type to the user callbacks. Previously only transport + // errors were forwarded, so CONNACK rejections (CONNECTION_REFUSED) were + // silently dropped and never surfaced to the application. + for (uint8_t i = 0; i < _onErrorUserCallbackCount; ++i) + { + _onErrorUserCallbacks[i](*err); } } diff --git a/src/helpers/bridges/MQTTBridge.cpp b/src/helpers/bridges/MQTTBridge.cpp index 3c3ac91f..9dcf5561 100644 --- a/src/helpers/bridges/MQTTBridge.cpp +++ b/src/helpers/bridges/MQTTBridge.cpp @@ -1139,7 +1139,14 @@ void MQTTBridge::initSlotClients() { _slots[index].last_tls_stack_err = error.esp_tls_stack_err; _slots[index].last_sock_errno = error.esp_transport_sock_errno; _slots[index].last_error_time = millis(); - if (error.esp_tls_last_esp_err != 0 || error.esp_tls_stack_err != 0 || error.esp_transport_sock_errno != 0) { + if (error.error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { + // Broker rejected the MQTT CONNECT itself — not a transport failure. + // return code: 1=protocol, 2=client-id rejected, 3=server unavailable, + // 4=bad username/password, 5=not authorized. Codes 3/4/5 point at a + // server-side lockout or auth problem rather than the network. + MQTT_DEBUG_PRINTLN("MQTT%d connection refused by broker (return code=%d)", + index + 1, (int)error.connect_return_code); + } else if (error.esp_tls_last_esp_err != 0 || error.esp_tls_stack_err != 0 || error.esp_transport_sock_errno != 0) { MQTT_DEBUG_PRINTLN("MQTT%d error: tls=%d, tls_stack=%d, sock=%d, type=%d", index + 1, error.esp_tls_last_esp_err, error.esp_tls_stack_err, error.esp_transport_sock_errno, error.error_type);