Ver failed, rc=-2 no monitor serial é o erro mais comum do PubSubClient, e a mensagem sozinha diz muito pouco. O PubSubClient rc=-2 significa que a conexão TCP (ou TLS) com o broker nunca chegou a ser aberta, então o problema quase sempre está no DNS, na porta, na rede ou no certificado, e não no MQTT em si. Este guia decifra cada código de estado de -4 a 5 e traz uma solução para cada um.
De Onde Vem o Valor rc
O PubSubClient armazena o resultado da última tentativa de conexão em uma variável de estado interna, que você lê com mqtt.state(). A maioria dos sketches de exemplo a imprime quando connect() retorna false:
if (!mqtt.connect(clientId)) {
Serial.print("failed, rc=");
Serial.println(mqtt.state());
}
Os valores são definidos como constantes em PubSubClient.h. Os valores negativos vêm da biblioteca e da camada de rede. Os positivos são os códigos de retorno que o broker enviou no pacote CONNACK, conforme definido pela especificação MQTT 3.1.1.
| rc | Constante | Camada | Significado em linguagem simples |
|---|---|---|---|
| -4 | MQTT_CONNECTION_TIMEOUT |
Biblioteca | Socket aberto, mas sem CONNACK (ou sem resposta ao ping) a tempo |
| -3 | MQTT_CONNECTION_LOST |
Rede | Uma conexão estabelecida caiu |
| -2 | MQTT_CONNECT_FAILED |
Rede | Não foi possível abrir o socket |
| -1 | MQTT_DISCONNECTED |
Biblioteca | Cliente desconectado normalmente |
| 0 | MQTT_CONNECTED |
Broker | Conectado |
| 1 | MQTT_CONNECT_BAD_PROTOCOL |
Broker | Versão do protocolo não aceita |
| 2 | MQTT_CONNECT_BAD_CLIENT_ID |
Broker | Client ID rejeitado |
| 3 | MQTT_CONNECT_UNAVAILABLE |
Broker | O broker não pode aceitar conexões agora |
| 4 | MQTT_CONNECT_BAD_CREDENTIALS |
Broker | Usuário ou senha incorretos |
| 5 | MQTT_CONNECT_UNAUTHORIZED |
Broker | Sem autorização para conectar |
O ponto-chave: com códigos negativos, o broker nunca viu você ou nunca respondeu. Com códigos positivos, o broker recebeu seu pacote CONNECT e o recusou deliberadamente.
Como Resolver o PubSubClient rc=-2
Como o rc=-2 é informado sempre que client.connect(host, port) falha no objeto de rede subjacente, ele tem muitas causas possíveis. Verifique-as nesta ordem.
1. O Wi-Fi Não Está Realmente Conectado
Chamar mqtt.connect() antes de WiFi.status() == WL_CONNECTED sempre retorna -2. Isso também acontece quando o access point derruba você e o seu loop verifica apenas o MQTT. Verifique o Wi-Fi primeiro em cada iteração e reconecte-o antes de mexer no MQTT.
2. O DNS Falha ou o Nome do Host Está Errado
Erros de digitação como broker.connectmq.com com um espaço no final, mqtt://broker.connectmq.com (uma URL em vez de um nome de host) ou prefixos http:// falham silenciosamente. O setServer() espera um nome de host puro ou um IPAddress. Teste o DNS diretamente:
IPAddress ip;
if (WiFi.hostByName("broker.connectmq.com", ip)) {
Serial.print("Resolved to ");
Serial.println(ip);
} else {
Serial.println("DNS lookup failed");
}
Se o DNS falhar, verifique se o DHCP forneceu um servidor DNS ou defina um explicitamente com WiFi.config().
3. Porta Errada para o Tipo de Cliente
Este é o erro clássico. A porta e o cliente de rede precisam combinar:
| Porta | Transporte | Cliente Arduino a usar |
|---|---|---|
| 1883 | MQTT puro sobre TCP | WiFiClient |
| 8883 | MQTT sobre TLS | WiFiClientSecure |
| 8083 / 8084 | MQTT sobre WebSocket | Não suportado pelo PubSubClient |
Um WiFiClient apontado para a 8883 abre um socket TCP e depois trava ou falha, porque o broker espera um handshake TLS, o que muitas vezes aparece como -2 ou -4. Um WiFiClientSecure apontado para a 1883 falha no handshake e retorna -2. O PubSubClient não fala WebSocket de forma alguma, então as portas 8083 e 8084 são para navegadores e ferramentas como as descritas em MQTT sobre WebSocket.
4. Problemas com o Certificado TLS
Com WiFiClientSecure, uma falha na verificação do certificado também é informada como rc=-2. Causas comuns:
- Nenhum certificado de CA definido. No ESP32, chame
setCACert()com a raiz que assinou o certificado do broker. O ConnectMQ usa Let's Encrypt, então a raiz é a ISRG Root X1. - Fixar (pinning) um certificado folha ou intermediário que já foi trocado. Os certificados Let's Encrypt têm vida curta; fixe a raiz, não a folha.
- Hora do sistema errada no ESP8266. O BearSSL verifica as datas de validade, então sincronize o relógio com
configTime()antes de conectar. - Falta de memória. O handshake TLS precisa de uma boa parte do heap; no ESP8266, um buffer MQTT grande somado ao TLS pode esgotá-lo.
No ESP32, você pode imprimir o erro TLS subjacente após uma tentativa malsucedida:
char err[128];
int code = netClient.lastError(err, sizeof(err));
Serial.printf("TLS error %d: %s\n", code, err);
Para isolar o problema, chame netClient.setInsecure() temporariamente. Se assim conectar, o problema está na configuração do certificado. Nunca publique um firmware com setInsecure().
5. A Rede Bloqueia MQTT de Saída
Redes corporativas, de escolas e algumas redes de convidados bloqueiam as portas de saída 1883 e 8883. Teste o mesmo sketch usando o roteador do celular. Se funcionar ali, peça a liberação da porta ou mova o dispositivo para outro segmento de rede.
6. Tentativas de Conexão Frequentes Demais
Se o broker vê tentativas fracassadas repetidas vindas do seu endereço IP, ele pode recusar conexões temporariamente. O ConnectMQ, por exemplo, bloqueia endereços IP após logins malsucedidos repetidos para proteger os clientes. Um loop de reconexão sem pausa pode transformar uma única senha errada em um bloqueio que depois parece um rc=-2. Sempre espere pelo menos alguns segundos entre as tentativas e aumente o intervalo após várias falhas.
Como Resolver o rc=-4 (Tempo Esgotado)
Aqui o socket foi aberto, mas o CONNACK não chegou dentro do timeout do socket (15 segundos por padrão). Causas típicas:
WiFiClientpuro em uma porta TLS, como descrito acima.- Sinal de Wi-Fi fraco com muita perda de pacotes. Imprima
WiFi.RSSI(); qualquer valor por volta de -80 dBm ou mais fraco não é confiável. - Código bloqueante. Se a conexão foi estabelecida antes, o -4 também pode aparecer mais tarde, quando
loop()não é chamado com frequência suficiente para responder aos pings de keep alive.
Como Resolver o rc=-3 (Conexão Perdida)
A conexão funcionou e depois caiu. Procure por:
- Client IDs duplicados. Quando um segundo dispositivo se conecta com o mesmo ID, o broker desconecta o primeiro. Duas placas gravadas com o mesmo sketch vão se derrubar alternadamente. Gere os IDs a partir do endereço MAC.
- Expiração do keep alive. Chamadas longas de
delay()ou leituras lentas de sensores deixammqtt.loop()sem execução. - Mensagens grandes ou frequentes demais. Os brokers impõem limites. No servidor MQTT público em broker.connectmq.com, destinado a testes, os clientes estão limitados a 64 KB por mensagem e 10 mensagens por segundo, e ultrapassar os limites pode encerrar a sessão.
Como Resolver os Códigos Positivos (1 a 5)
rc=1: Protocolo Inválido
O PubSubClient envia MQTT 3.1.1 por padrão. Você só verá este código se compilou com MQTT_VERSION definido como 3.1 contra um broker que o rejeita. Remova essa substituição.
rc=2: Client ID Rejeitado
Um client ID vazio é o culpado mais comum. O broker público do ConnectMQ exige um client ID não vazio, mesmo em conexões anônimas. Em um broker privado do ConnectMQ, os client IDs ficam vinculados às credenciais emitidas no portal, então use exatamente o client ID que você recebeu.
rc=3: Servidor Indisponível
O broker está no ar, mas não está aceitando conexões, por exemplo durante uma manutenção ou quando uma cota de conexões foi atingida. Espere e tente de novo. Se o problema persistir no seu próprio broker, verifique se você ultrapassou o limite de conexões do seu plano.
rc=4: Usuário ou Senha Incorretos
Copie as credenciais novamente do portal e fique atento a caracteres invisíveis. Lembre-se de que connect(id, user, pass) recebe o client ID primeiro; inverter a ordem é surpreendentemente comum.
rc=5: Não Autorizado
O broker entendeu as credenciais, mas recusa este cliente, por exemplo porque o usuário e o client ID não pertencem um ao outro. Confira novamente os três valores.
Uma Função de Conexão com Diagnóstico
Coloque isto em qualquer sketch para obter um motivo legível em vez de um simples número:
const char* mqttStateText(int s) {
switch (s) {
case -4: return "timeout (no CONNACK) - check port/TLS match and signal";
case -3: return "connection lost - duplicate client ID or keep alive";
case -2: return "socket failed - Wi-Fi, DNS, port, firewall or TLS cert";
case -1: return "disconnected";
case 0: return "connected";
case 1: return "bad protocol version";
case 2: return "client ID rejected - empty or not allowed";
case 3: return "server unavailable - retry later";
case 4: return "bad username or password";
case 5: return "not authorised";
default: return "unknown";
}
}
bool connectWithDiagnostics() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Wi-Fi not connected, skipping MQTT");
return false;
}
if (mqtt.connect(DEVICE_ID)) {
Serial.println("MQTT connected");
return true;
}
int s = mqtt.state();
Serial.printf("MQTT failed rc=%d: %s\n", s, mqttStateText(s));
return false;
}
Checklist Rápido de Isolamento
- Seu computador consegue alcançar o broker? Execute
mosquitto_sub -h broker.connectmq.com -p 1883 -i test-$RANDOM -t "connectmq/demo/check/#" -v. Se falhar, o problema é a sua rede, não a placa. - A placa resolve o nome do host? Use o trecho de DNS acima.
- Ela conecta na 1883 com
WiFiCliente um client ID anônimo e único? Se sim, o problema está no TLS ou nas credenciais. - Ela conecta na 8883 com
setInsecure()? Se sim, corrija o certificado da CA. - Ela conecta com a CA, mas falha com as credenciais? Confira de novo usuário, senha e client ID.
Depois de conectado, o próximo problema que as pessoas encontram é o tamanho das mensagens; veja tamanho do buffer do PubSubClient. Para um passo a passo completo da biblioteca, leia nosso tutorial do PubSubClient para Arduino e, para um projeto completo, veja o guia principal de tutorial IoT com ESP32.
Pare de Caçar Códigos rc com um Broker MQTT Gerenciado
Muitos erros rc=-2 e rc=-4 vêm de brokers auto-hospedados com certificados expirados, portas de firewall fechadas ou serviços que travaram. Um broker MQTT gerenciado como o ConnectMQ elimina essas variáveis: TLS na 8883 com um certificado Let's Encrypt renovado automaticamente, credenciais geradas para você e um cliente MQTT no navegador dentro do portal, para que você confirme que o lado do broker funciona antes de depurar o dispositivo. Crie um broker Serverless gratuito em app.connectmq.com, sem precisar de cartão de crédito.
Perguntas frequentes
O que significa rc=-2 no PubSubClient?
Significa que não foi possível abrir a conexão de rede com o broker. O broker nunca recebeu seu pacote CONNECT, então verifique o Wi-Fi, o DNS, a porta e, no caso de TLS, o certificado da CA.
Por que recebo rc=-2 apenas na porta 8883?
Sua configuração TLS está falhando. Certifique-se de usar WiFiClientSecure, carregar o certificado raiz correto (ISRG Root X1 para brokers com Let's Encrypt) e, no ESP8266, acertar o relógio antes de conectar.
Minha placa conecta e depois mostra rc=-3 a cada poucos segundos. Por quê?
Na maioria das vezes, outro dispositivo ou ferramenta está usando o mesmo client ID, então o broker fica substituindo uma sessão pela outra. Dê a cada dispositivo um ID único, por exemplo baseado no endereço MAC.
O rc=5 é diferente do rc=4?
Sim. O rc=4 significa que o usuário ou a senha estão errados. O rc=5 significa que as credenciais foram entendidas, mas este cliente não tem permissão para conectar, muitas vezes porque o client ID não corresponde às credenciais.



