MQTT TLS Connection Fails on ESP32-C3 but Works on Linux(error: 0x8008)

The problem

MQTT over TLS connection fails on ESP32-C3 with ESPHome, but the exact same credentials work successfully on Linux using mosquitto_sub. The connection briefly succeeds (CONNACK received) but immediately disconnects with a TLS error.

Which version of ESPHome has the issue?

2025.9.1

What type of installation are you using?

Home Assistant Add-on

What platform are you using?

ESP32

Component causing the issue

mqtt

YAML Config

# ========= MQTT Connection Test - Simplified Version =========
# For testing OneNET MQTT connection

substitutions:
  device_name: "mqtt-test-c3"
  friendly_name: "MQTT-Test"

esphome:
  name: ${device_name}
  friendly_name: ${friendly_name}
  on_boot:
    priority: -10
    then:
      - delay: 8s         # Wait for Wi-Fi + SNTP sync
      - mqtt.enable:      # Delayed MQTT startup
      - logger.log: "System boot complete, MQTT enabled"

esp32:
  board: airm2m_core_esp32c3
  framework:
    type: esp-idf

logger:
  level: DEBUG

api:

json:

# Time synchronization - MQTT requires accurate timestamps
time:
  - platform: sntp
    id: sntp_time
    servers:
      - ntp.aliyun.com
      - time.windows.com
    timezone: Asia/Shanghai
    on_time_sync:
      - logger.log: "✓ Time synchronized successfully"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  on_connect:
    - logger.log: "✓ Wi-Fi connected successfully"
  on_disconnect:
    - logger.log: "✗ Wi-Fi disconnected"

ota:
  - platform: esphome
    password: !secret ota_password

# MQTT Configuration - China Mobile OneNET Platform
mqtt:
  broker: "nkKRY36VE6.mqttstls.acc.cmcconenet.cn"  # OneNET MQTT server (Note: mqttstls not mqtts)
  port: 8883                                        # TLS encrypted port
  username: "nkKRY36VE6"                           # Product ID
  password: "version=2018-10-31&res=products%2FnkKRY36VE6%2Fdevices%2Fmypanel&et=1791185468&method=md5&sign=v%2BxH6eBLz%2BI1NXNgzieDcA%3D%3D"
  client_id: "mypanel"                             # Device name
  clean_session: true
  topic_prefix: null
  enable_on_boot: false                             # Delayed startup, wait for SNTP sync
  discovery: false
  discovery_retain: false
  skip_cert_cn_check: true                          # Skip certificate CN check
  use_abbreviations: false                          # Disable abbreviations
  idf_send_async: false                             # ESP-IDF synchronous send
  reboot_timeout: 0s                                # Disable reboot timeout
  keepalive: 60s
  log_topic: null                                   # Disable log topic
  birth_message:                                    # Disable birth message
  will_message:                                     # Disable will message
  
  # OneNET MQTT TLS Certificate
  certificate_authority: |-
    -----BEGIN CERTIFICATE-----
    MIIDOzCCAiOgAwIBAgIJAPCCNfxANtVEMA0GCSqGSIb3DQEBCwUAMDQxCzAJBgNV
    BAYTAkNOMQ4wDAYDVQQKDAVDTUlPVDEVMBMGA1UEAwwMT25lTkVUIE1RVFRTMB4X
    DTE5MDUyOTAxMDkyOFoXDTQ5MDUyMTAxMDkyOFowNDELMAkGA1UEBhMCQ04xDjAM
    BgNVBAoMBUNNSU9UMRUwEwYDVQQDDAxPbmVORVQgTVFUVFMwggEiMA0GCSqGSIb3
    DQEBAQUAA4IBDwAwggEKAoIBAQC/VvJ6lGWfy9PKdXKBdzY83OERB35AJhu+9jkx
    5d4SOtZScTe93Xw9TSVRKrFwu5muGgPusyAlbQnFlZoTJBZY/745MG6aeli6plpR
    r93G6qVN5VLoXAkvqKslLZlj6wXy70/e0GC0oMFzqSP0AY74icANk8dUFB2Q8usS
    UseRafNBcYfqACzF/Wa+Fu/upBGwtl7wDLYZdCm3KNjZZZstvVB5DWGnqNX9HkTl
    U9NBMS/7yph3XYU3mJqUZxryb8pHLVHazarNRppx1aoNroi+5/t3Fx/gEa6a5PoP
    ouH35DbykmzvVE67GUGpAfZZtEFE1e0E/6IB84PE00llvy3pAgMBAAGjUDBOMB0G
    A1UdDgQWBBTTi/q1F2iabqlS7yEoX1rbOsz5GDAfBgNVHSMEGDAWgBTTi/q1F2ia
    bqlS7yEoX1rbOsz5GDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAL
    aqJ2FgcKLBBHJ8VeNSuGV2cxVYH1JIaHnzL6SlE5q7MYVg+Ofbs2PRlTiWGMazC7
    q5RKVj9zj0z/8i3ScWrWXFmyp85ZHfuo/DeK6HcbEXJEOfPDvyMPuhVBTzuBIRJb
    41M27NdIVCdxP6562n6Vp0gbE8kN10q+ksw8YBoLFP0D1da7D5WnSV+nwEIP+F4a
    3ZX80bNt6tRj9XY0gM68mI60WXrF/qYL+NUz+D3Lw9bgDSXxpSN8JGYBR85BxBvR
    NNAhsJJ3yoAvbPUQ4m8J/CoVKKgcWymS1pvEHmF47pgzbbjm5bdthlIx+swdiGFa
    WzdhzTYwVkxBaU+xf/2w
    -----END CERTIFICATE-----
  
  # MQTT connection success callback
  on_connect:
    - logger.log:
        level: INFO
        format: "✓✓✓ MQTT Connected Successfully! ✓✓✓"
    - lambda: |-
        ESP_LOGI("mqtt_test", "========================================");
        ESP_LOGI("mqtt_test", "✓ MQTT Connected to OneNET Platform!");
        ESP_LOGI("mqtt_test", "✓ Broker: nkKRY36VE6.mqttstls.acc.cmcconenet.cn:8883");
        ESP_LOGI("mqtt_test", "✓ Client ID: mypanel");
        ESP_LOGI("mqtt_test", "========================================");
        id(mqtt_connected) = true;
  
  # MQTT disconnection callback
  on_disconnect:
    - logger.log:
        level: WARN
        format: "✗✗✗ MQTT Disconnected! ✗✗✗"
    - lambda: |-
        ESP_LOGW("mqtt_test", "========================================");
        ESP_LOGW("mqtt_test", "✗ MQTT Connection Lost");
        ESP_LOGW("mqtt_test", "✗ Will attempt auto-reconnect...");
        ESP_LOGW("mqtt_test", "========================================");
        id(mqtt_connected) = false;
  
  # Subscribe to test topic
  on_message:
    - topic: "$sys/nkKRY36VE6/mypanel/thing/property/post_reply"
      then:
        - lambda: |-
            ESP_LOGI("mqtt_test", "========================================");
            ESP_LOGI("mqtt_test", "Received OneNET response message:");
            ESP_LOGI("mqtt_test", "%s", x.c_str());
            ESP_LOGI("mqtt_test", "========================================");
            
            // Parse response code
            if (x.find("\"code\":200") != std::string::npos) {
              ESP_LOGI("mqtt_test", "✓✓✓ Data Upload Successful! ✓✓✓");
            } else if (x.find("\"code\":") != std::string::npos) {
              ESP_LOGW("mqtt_test", "✗✗✗ Data Upload Failed! ✗✗✗");
            }

network:

# Global variables
globals:
  - id: mqtt_connected
    type: bool
    initial_value: 'false'
  - id: test_counter
    type: int
    initial_value: '0'

# MQTT connection status sensor
text_sensor:
  - platform: template
    name: "MQTT Status"
    id: mqtt_status
    icon: "mdi:cloud-check"
    lambda: |-
      if (id(mqtt_connected)) {
        return std::string("✓ Connected");
      } else {
        return std::string("✗ Disconnected");
      }
    update_interval: 5s

# Test counter
sensor:
  - platform: template
    name: "Test Send Count"
    id: test_send_count
    icon: "mdi:counter"
    lambda: |-
      return id(test_counter);
    update_interval: 10s

# Periodic connection status check: Display MQTT connection status every 30 seconds
interval:
  - interval: 30s
    then:
      - lambda: |-
          if (id(mqtt_connected)) {
            ESP_LOGI("mqtt_test", "========================================");
            ESP_LOGI("mqtt_test", "✓ MQTT Connection Maintained...");
            ESP_LOGI("mqtt_test", "✓ Use manual button to send test data");
            ESP_LOGI("mqtt_test", "========================================");
          } else {
            ESP_LOGW("mqtt_test", "⚠ MQTT Not Connected, Waiting for Reconnection...");
          }

# Manual test button (can be triggered via Home Assistant)
button:
  - platform: template
    name: "Send Test Data"
    icon: "mdi:send"
    on_press:
      - if:
          condition:
            mqtt.connected:
          then:
            - logger.log: "Manually triggered test upload..."
            - lambda: |-
                id(test_counter) += 1;
            
            - mqtt.publish:
                topic: "$sys/nkKRY36VE6/mypanel/thing/property/post"
                payload: !lambda |-
                  #include <ArduinoJson.h>
                  
                  // Get current timestamp
                  auto time_now = id(sntp_time).now();
                  int64_t timestamp = time_now.timestamp * 1000LL;
                  
                  // Create JSON document
                  JsonDocument doc;
                  doc["id"] = to_string(millis());
                  doc["version"] = "1.0";
                  
                  JsonObject params = doc["params"].to<JsonObject>();
                  
                  JsonObject temp = params["temperature"].to<JsonObject>();
                  temp["value"] = 23.5;
                  temp["time"] = timestamp;
                  
                  JsonObject hum = params["humidity"].to<JsonObject>();
                  hum["value"] = 55.0;
                  hum["time"] = timestamp;
                  
                  JsonObject press = params["pressure"].to<JsonObject>();
                  press["value"] = 1015.0;
                  press["time"] = timestamp;
                  
                  // Serialize
                  std::string json_msg;
                  serializeJson(doc, json_msg);
                  
                  ESP_LOGI("mqtt_test", "Manually sending test data: %s", json_msg.c_str());
                  return json_msg;
          else:
            - logger.log:
                level: ERROR
                format: "✗ MQTT Not Connected, Cannot Send Data!"

Anything in the logs that might be useful for us?

[20:04:30.119][W][component:326]: mqtt cleared Warning flag
[20:04:30.119][I][mqtt:309]: Connected
[20:04:30.244][W][component:443]: mqtt took a long time for an operation (115 ms)
[20:04:30.244][W][component:446]: Components should block for at most 30 ms
[20:04:30.324][E][mqtt.idf:167]: MQTT_EVENT_ERROR
[20:04:30.324][E][mqtt.idf:169]: Last error code reported from esp-tls: 0x8008
[20:04:30.324][E][mqtt.idf:170]: Last tls stack error number: 0x0
[20:04:30.324][E][mqtt.idf:171]: Last captured errno : 0 (Success)
[20:04:30.324][D][esp-idf:000][mqtt_task]: E (15263) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read(): EOF
[20:04:30.324][D][esp-idf:000][mqtt_task]: E (15264) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read() error: errno=119
[20:04:30.324][D][esp-idf:000][mqtt_task]: E (15264) mqtt_client: mqtt_process_receive: mqtt_message_receive() returned -2
[20:04:30.324][W][mqtt:358]: Disconnected: TCP disconnected

Additional information

mosquitto_sub -h nkKRY36VE6.mqttstls.acc.cmcconenet.cn -p 8883 \
  --cafile onenet.pem --insecure \
  -i mypanel -u nkKRY36VE6 \
  -P 'version=2018-10-31&res=products%2FnkKRY36VE6%2Fdevices%2Fmypanel&et=1791185468&method=md5&sign=v%2BxH6eBLz%2BI1NXNgzieDcA%3D%3D' \
  -t '$sys/nkKRY36VE6/mypanel/#' \
   -k 60 -d                      
Client mypanel sending CONNECT
Client mypanel received CONNACK (0)
Client mypanel sending SUBSCRIBE (Mid: 1, Topic: $sys/nkKRY36VE6/mypanel/#, QoS: 0, Options: 0x00)
Client mypanel received SUBACK
Subscribed (mid: 1): 0
Client mypanel sending CONNECT
Client mypanel received CONNACK (0)
Client mypanel sending SUBSCRIBE (Mid: 2, Topic: $sys/nkKRY36VE6/mypanel/#, QoS: 0, Options: 0x00)
Client mypanel received SUBACK
Subscribed (mid: 2): 0
Client mypanel sending CONNECT
Client mypanel received CONNACK (0)
Client mypanel sending SUBSCRIBE (Mid: 3, Topic: $sys/nkKRY36VE6/mypanel/#, QoS: 0, Options: 0x00)
Client mypanel received SUBACK
Subscribed (mid: 3): 0



It works in linux with same config.

github issue:

It seems related to this issue: MQTT SSL/TLS issue with ESP32 not connecting with broker (Solved) - Networking, Protocols, and Devices - Arduino Forum
But ESPHome does not have options to configure TLS version.

I encountered a new error when using EMQX
11:37:45.094][W][component:287]: mqtt set Warning flag: unspecified
[11:37:45.094][D][mqtt:216]: Resolving broker IP address
[11:37:45.108][D][mqtt:247]: Resolved broker IP address to 63.178.38.52
[11:37:45.108][I][mqtt:268]: Connecting
[11:37:47.449][E][mqtt.idf:167]: MQTT_EVENT_ERROR
[11:37:47.463][E][mqtt.idf:174]: Connection refused error: 0x5
[11:37:47.463][D][esp-idf:000][mqtt_task]: E (15828) mqtt_client: MQTT connect failed

我也遇到了同样的问题,我怀疑这跟onenet平台有关。我用mqttx可以正常连接onnet上的mqtt。然后我使用mosquitto模拟onenet上mqtt服务端的环境,esphome可以正常连接到mosquitto并发布消息。我使用的设备是esp32-c3,esphome版本为2025.10.3。

I encountered the same issue and suspect it’s related to the OneNet platform. I can connect to the MQTT server on OneNet normally using MQTTX. Then, I used Mosquitto to simulate the MQTT server environment on OneNet, and EspHome successfully connected to Mosquitto and published messages. The device I used is an ESP32-C3, and the EspHome version is 2025.10.3.