Broker Testing

Test an ESP32 MQTT Connection Step by Step

ESP32 not connecting to MQTT? Test Wi-Fi, DNS, the TCP port, client ID, credentials and buffer size one by one with a diagnostic sketch and serial logs.

Updated · 8 min read

Test an ESP32 MQTT Connection Step by Step

When an ESP32 refuses to talk to an MQTT broker, the serial monitor usually shows one unhelpful line: failed, rc=-2 try again in 5 seconds. The fastest way out is to test the connection layer by layer — Wi-Fi, DNS, TCP port, MQTT handshake, then publishing — and stop at the first layer that fails.

This guide gives you a diagnostic sketch for the Arduino core (ESP32 core 3.x with PubSubClient 2.8) that does exactly that, explains every result, and shows how to confirm from the broker side that the board is really there.

The checklist at a glance

StepWhat can go wrongHow it shows up
1. Serial logWrong baud rate, no log at allGarbage or silence in the monitor
2. Wi-FiWrong SSID/password, 5 GHz network, weak signalWiFi.status() never reaches WL_CONNECTED (3)
3. DNSNo DNS server from DHCP, typo in hosthostByName fails
4. TCP portFirewall, wrong port, TLS port with a plain clientrc=-2 from PubSubClient
5. MQTT CONNECTDuplicate client ID, bad credentials, ACLrc=2, rc=4, rc=5
6. PublishPacket bigger than the bufferpublish() returns false
7. Staying connectedloop() not called, keep alive too shortrc=-3 after a while

Step 1: get a readable serial log

Set the monitor to the same speed as Serial.begin() — 115200 is the convention. In the Arduino IDE, also set Tools → Core Debug Level to Info or Verbose: the ESP32 core then prints Wi-Fi events and TLS errors that your own sketch never sees. In PlatformIO, use monitor_speed = 115200 and build_flags = -DCORE_DEBUG_LEVEL=4.

Step 2–6: the diagnostic sketch

Flash this sketch before touching your real firmware. It checks every layer in order and prints exactly where it stops.

esp32_mqtt_check.ino
#include <WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "your-ssid";
const char* WIFI_PASS = "your-wifi-password";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* MQTT_USER = "username";   // nullptr if the broker allows anonymous access
const char* MQTT_PASS = "password";

WiFiClient net;
PubSubClient mqtt(net);
String clientId;

bool check() {
  Serial.println("\n[1] Wi-Fi");
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  unsigned long t0 = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - t0 < 20000) { delay(250); Serial.print('.'); }
  if (WiFi.status() != WL_CONNECTED) {
    Serial.printf("\nWi-Fi failed, status=%d\n", WiFi.status());
    return false;
  }
  Serial.printf("\nIP %s  gateway %s  RSSI %d dBm\n", WiFi.localIP().toString().c_str(),
                WiFi.gatewayIP().toString().c_str(), WiFi.RSSI());

  Serial.println("[2] DNS");
  IPAddress ip;
  if (!WiFi.hostByName(MQTT_HOST, ip)) { Serial.println("DNS lookup failed"); return false; }
  Serial.printf("%s -> %s\n", MQTT_HOST, ip.toString().c_str());

  Serial.println("[3] TCP port");
  if (!net.connect(ip, MQTT_PORT)) { Serial.println("TCP connect failed"); return false; }
  Serial.println("TCP OK");
  net.stop();

  Serial.println("[4] MQTT CONNECT");
  clientId = "esp32-" + WiFi.macAddress();
  clientId.replace(":", "");
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setBufferSize(1024);
  mqtt.setKeepAlive(30);
  if (!mqtt.connect(clientId.c_str(), MQTT_USER, MQTT_PASS)) {
    Serial.printf("MQTT failed, rc=%d\n", mqtt.state());
    return false;
  }
  Serial.printf("MQTT OK as %s\n", clientId.c_str());

  Serial.println("[5] PUBLISH");
  String topic = "testmqtt/esp32-check/" + clientId + "/hello";
  bool ok = mqtt.publish(topic.c_str(), "ESP32 connection test passed");
  Serial.printf("publish to %s: %s\n", topic.c_str(), ok ? "OK" : "FAILED");
  return ok;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println(check() ? "\nALL CHECKS PASSED" : "\nCHECK FAILED - see the last step above");
}

void loop() {
  mqtt.loop();
}

Reading the results

Wi-Fi status codes

statusMeaningFix
1 WL_NO_SSID_AVAILNetwork not foundCheck the SSID spelling; make sure it broadcasts on 2.4 GHz
4 WL_CONNECT_FAILEDRejected, usually wrong passwordRe-type the password; WPA3-only networks may need WPA2/WPA3 mixed mode
6 WL_DISCONNECTEDStill trying or droppedMove closer; RSSI below about -80 dBm is unreliable

A good RSSI is roughly -50 to -70 dBm. If Wi-Fi connects but keeps dropping later, see ESP32 Wi-Fi and MQTT disconnects.

DNS and TCP

DNS lookup failed means the board got no usable DNS server from DHCP or the host name is wrong. Check the same name from a laptop on the same network with nslookup broker.connectmq.com. As a temporary test you can connect by IP, but do not ship that.

TCP connect failed (and rc=-2 in your own firmware) means nothing answered on that host and port. Common causes: a guest network or corporate firewall blocking 1883, a typo in the port, or using port 8883 with a plain WiFiClient — TLS ports need WiFiClientSecure and a CA certificate, as shown in ESP32 MQTT over TLS. Confirm from a laptop on the same Wi-Fi with nc -vz broker.connectmq.com 1883.

PubSubClient return codes

rcConstantUsual cause
-4MQTT_CONNECTION_TIMEOUTNo CONNACK in time, or keep alive expired
-3MQTT_CONNECTION_LOSTConnection dropped; loop() not called often enough
-2MQTT_CONNECT_FAILEDTCP connect failed (see above)
-1MQTT_DISCONNECTEDClean disconnect / never connected
1MQTT_CONNECT_BAD_PROTOCOLBroker does not accept MQTT 3.1.1
2MQTT_CONNECT_BAD_CLIENT_IDClient ID rejected (empty, too long, invalid characters)
3MQTT_CONNECT_UNAVAILABLEBroker unavailable
4MQTT_CONNECT_BAD_CREDENTIALSWrong username or password
5MQTT_CONNECT_UNAUTHORIZEDNot authorized — credentials missing or client not allowed

Positive values are the broker's own CONNACK answer, so the network is fine and only configuration remains. The reason code reference lists the matching MQTT codes, and PubSubClient not connecting goes deeper into each one.

Publish returns false

PubSubClient's default buffer is 256 bytes and must hold the whole packet: header, topic and payload. A JSON payload of 200 bytes on a long topic already exceeds it, and publish() simply returns false with no message on the broker. Call setBufferSize() before connecting; the packet size calculator tells you how big a packet really is.

Step 7: staying connected

mqtt.loop() must run often — at least several times per keep-alive interval. A delay(60000) in loop() or a blocking sensor read guarantees rc=-3 after about one and a half keep-alive periods, because the broker never hears a PINGREQ. Replace long delays with millis() timers, and reconnect with a backoff instead of blocking in a while (!mqtt.connected()) loop.

Confirm from the broker side

A serial line saying "OK" is the device's opinion. Verify it independently: open the online MQTT client, connect to the same broker and subscribe to testmqtt/esp32-check/#. Reset the board and you should see the hello message arrive within a few seconds. From a terminal the same check is:

Watch for the ESP32's test message
mosquitto_sub -h broker.connectmq.com -p 1883 \
  -u "$MQTT_USER" -P "$MQTT_PASS" \
  -t 'testmqtt/esp32-check/#' -v

Watch for your ESP32 in the browser

Most ESP32 MQTT problems are not MQTT problems at all — they are Wi-Fi, DNS or port issues hidden behind a single return code. Test one layer at a time, read the exact status or rc value, and confirm on the broker side before you move on to your real firmware. For the full Arduino setup, continue with ESP32 MQTT with Arduino.

Frequently asked questions

What does "failed, rc=-2" mean on an ESP32?

It is PubSubClient's MQTT_CONNECT_FAILED: the TCP connection to the broker could not be opened. The cause is below MQTT — no Wi-Fi, wrong host or port, DNS failure, a firewall, or a TLS port used with a plain WiFiClient.

Why does my ESP32 connect but publish() returns false?

Most often the message is larger than PubSubClient's buffer, which is 256 bytes by default including the topic and header. Call setBufferSize(1024) or larger before connecting, and check the return value of every publish.

Does the ESP32 support 5 GHz Wi-Fi for MQTT?

The classic ESP32, S2, S3 and C3 only have 2.4 GHz radios, so they cannot join a 5 GHz-only network. Newer chips such as the ESP32-C5 support dual band. Check your exact module before debugging MQTT.