Objetivos de aprendizado
Depois de ler este artigo, você vai conseguir:
- Identificar pelo código de desconexão por que a sessão caiu
- Corrigir as causas mais comuns: pasta de sessão perdida, duas instâncias e aparelho removido
- Montar uma reconexão que não entra em loop nem apaga a sessão sem querer
Nesta página
- O que significa o bot pedir QR code de novo?
- Como ler o motivo da desconexão no Baileys?
- Por que a sessão some a cada restart?
- Como saber se duas instâncias disputam a sessão?
- O celular removeu o aparelho ou ficou inativo?
- E no whatsapp-web.js?
- Como evitar que a sessão caia de novo?
- Como fazer isso na Square Cloud
- Perguntas frequentes
Seu bot de WhatsApp funcionava, e de repente o log mostra a conexão fechada ou o terminal volta a pedir um QR code. Você escaneia, ele funciona por algumas horas ou até o próximo restart, e o ciclo recomeça. Quase sempre o problema não é a biblioteca: é a sessão, ou seja, as credenciais que provam ao WhatsApp que aquele aparelho vinculado é você.
Os exemplos cobrem Baileys e whatsapp-web.js, as duas bibliotecas não oficiais mais usadas, com a versão LTS ativa do Node.js e a API do Baileys 7. Se ainda não tem um bot rodando, comece por como fazer um bot de WhatsApp.
O que significa o bot pedir QR code de novo?#
Um bot não oficial se conecta como um aparelho vinculado, igual ao WhatsApp Web. No primeiro pareamento, o WhatsApp entrega credenciais que a biblioteca grava em disco. Nas execuções seguintes, ela lê essas credenciais e conecta sem QR.
Pedir QR de novo significa que, na hora de conectar, não havia sessão válida. Só existem dois motivos: a sessão não estava lá (pasta apagada, outro caminho) ou o WhatsApp a invalidou (aparelho removido, sessão substituída). Descobrir qual dos dois é o diagnóstico inteiro.
Como ler o motivo da desconexão no Baileys?#
O evento connection.update traz lastDisconnect.error.output.statusCode quando a conexão fecha. Estes são os códigos do enum DisconnectReason do Baileys:
| Código | Nome | Significado | O que fazer |
|---|---|---|---|
| 401 | loggedOut |
O WhatsApp encerrou a sessão deste aparelho | Apagar a pasta e parear de novo |
| 440 | connectionReplaced |
Outra conexão assumiu a mesma sessão | Achar e desligar a outra instância |
| 500 | badSession |
Credenciais corrompidas ou incompletas | Apagar a pasta e parear de novo |
| 515 | restartRequired |
O WhatsApp pediu para reiniciar o socket | Reconectar |
| 428 / 408 | connectionClosed / connectionLost |
Queda de rede ou timeout | Reconectar com espera |
Em vez de reconectar às cegas, registre o código e trate cada caso. O exemplo abaixo reconecta com espera crescente e só desiste nos códigos em que repetir não adianta. Defina WA_PHONE com o número do bot, só dígitos e com código do país, e AUTH_DIR com a pasta da sessão:
import makeWASocket, {
DisconnectReason,
useMultiFileAuthState,
} from "baileys";
const AUTH_DIR = process.env.AUTH_DIR ?? "auth_info";
const PHONE = process.env.WA_PHONE;
let tentativas = 0;
async function start() {
const { state, saveCreds } = await useMultiFileAuthState(AUTH_DIR);
const sock = makeWASocket({ auth: state });
let codeRequested = false;
sock.ev.on("creds.update", saveCreds);
sock.ev.on("connection.update", async ({ connection, lastDisconnect, qr }) => {
if (qr && !codeRequested && !sock.authState.creds.registered) {
if (!PHONE) return console.error("Defina WA_PHONE para parear.");
codeRequested = true; // o qr se renova; peça o código uma vez por conexão
console.log("Código de pareamento:", await sock.requestPairingCode(PHONE));
}
if (connection === "open") {
tentativas = 0;
console.log("Conectado ao WhatsApp.");
}
if (connection === "close") {
const code = lastDisconnect?.error?.output?.statusCode;
console.error("Conexão fechada. Código:", code);
if (code === DisconnectReason.loggedOut || code === DisconnectReason.badSession) {
console.error(`Sessão inválida. Apague a pasta ${AUTH_DIR} e pareie de novo.`);
process.exit(0); // sai sem erro: quem reinicia em erro não entra em loop
}
if (code === DisconnectReason.connectionReplaced) {
console.error("Outra instância usa esta sessão. Encerrando.");
process.exit(0);
}
const espera = Math.min(30_000, 1_000 * 2 ** tentativas++);
setTimeout(start, espera);
}
});
}
start();O código não apaga a pasta sozinho, e isso é proposital: apagar a sessão por engano é o jeito mais rápido de transformar uma queda de rede em um novo pareamento. Quem decide é você, olhando o log.
Nos casos sem volta (401, 500 e 440), o processo encerra com código 0, sem erro. Um supervisor que reinicia o bot quando ele sai com erro, como o reinício automático de uma hospedagem, traria o processo de volta e criaria um loop: no 401 e no 500, com a mesma sessão inválida; no 440, expulsando a outra instância.
Por que a sessão some a cada restart?#
É a causa mais comum. A pasta de autenticação precisa ficar num disco que sobreviva ao reinício do processo. Ela some quando:
- O bot roda em plataforma com disco efêmero, que recria o sistema de arquivos a cada deploy ou reinício. A documentação do whatsapp-web.js avisa que o
LocalAuthprecisa de um sistema de arquivos persistente e não serve para hosts efêmeros como o Heroku. - O caminho muda: você usa um caminho relativo e executa o bot de pastas diferentes.
- Você reenvia o projeto inteiro (ZIP ou git) e a pasta de sessão é sobrescrita ou removida sem você perceber.
Para conferir, rode o bot, pareie, pare o processo e rode de novo. Se pedir QR ou código outra vez, a pasta não está sendo lida. Liste o conteúdo de AUTH_DIR antes e depois do restart: tem de haver um creds.json e vários arquivos de chaves.
Em produção, a documentação do Baileys recomenda guardar o estado de autenticação em banco de dados, não em arquivos, e trata o useMultiFileAuthState como um guia de como escrever esse armazenamento. Se você perde a pasta com frequência, um banco é o caminho. O guia de bot de WhatsApp 24/7 mostra o básico da sessão em disco.
Como saber se duas instâncias disputam a sessão?#
O sintoma é o código 440 (connectionReplaced) e um bot que cai a cada poucos segundos. Quando uma segunda conexão usa as mesmas credenciais, a anterior é derrubada. Se cada instância reconecta sozinha, elas ficam se expulsando.
Os culpados de sempre:
- Você deixou o bot rodando no seu PC e subiu o mesmo no servidor.
- O deploy novo sobe antes de o processo antigo morrer.
- Um supervisor de processos como o PM2, ou um
restart: always, mantém uma cópia viva que você não vê. - Você copiou a pasta de sessão para outro lugar e rodou os dois.
A correção é garantir uma única instância por sessão. Se precisa testar localmente, pareie um segundo número de teste em vez de reutilizar a pasta de produção.
O celular removeu o aparelho ou ficou inativo?#
O código 401 (loggedOut) quer dizer que o WhatsApp encerrou aquele aparelho vinculado. Duas causas:
- Alguém removeu o aparelho em Configurações, Dispositivos conectados, ou saiu da conta no celular.
- O celular principal ficou mais de 14 dias sem uso. Segundo a Central de Ajuda do WhatsApp, o celular não precisa ficar online para os aparelhos vinculados funcionarem, mas eles são desconectados se você não usar o celular por mais de 14 dias.
O limite de aparelhos também conta: a Central de Ajuda informa quantos aparelhos dá para vincular a uma conta. Se você já usa WhatsApp Web, app de desktop e outros bots no mesmo número, confira a lista em Dispositivos conectados e remova o que não usa.
Nos dois casos, a única saída é apagar a pasta de sessão e parear de novo. Reconectar com as credenciais antigas só repete o 401.
E no whatsapp-web.js?#
O whatsapp-web.js guarda a sessão com o LocalAuth, que salva os dados do navegador na pasta .wwebjs_auth por padrão. Sem authStrategy, o cliente não persiste nada e pede QR em toda execução:
const { Client, LocalAuth } = require("whatsapp-web.js");
const qrcode = require("qrcode-terminal");
const client = new Client({
authStrategy: new LocalAuth({
clientId: "bot-principal",
dataPath: process.env.AUTH_DIR ?? ".wwebjs_auth",
}),
});
client.on("qr", (qr) => qrcode.generate(qr, { small: true }));
client.on("ready", () => console.log("Conectado ao WhatsApp."));
client.on("disconnected", (reason) => {
// reason é "LOGOUT" ou um estado do WhatsApp Web, como CONFLICT ou UNPAIRED
console.error("Desconectado:", reason);
});
client.initialize();O evento disconnected recebe "LOGOUT" quando a sessão foi encerrada, ou um estado como CONFLICT (outra sessão assumiu, o equivalente ao 440) ou UNPAIRED (o aparelho foi desvinculado). As causas são as mesmas do Baileys: pasta perdida, duas instâncias, aparelho removido. Há ainda uma causa própria dele: como um Chromium roda ao lado do bot, a falta de memória pode derrubar o navegador e levar a conexão junto. Se o processo morre sem mensagem clara, olhe o consumo de RAM primeiro.
Como evitar que a sessão caia de novo?#
- Uma sessão, uma instância. Nunca rode a mesma pasta em dois lugares.
- Pasta persistente e fora do código. Defina
AUTH_DIRpor variável de ambiente e mantenha-a fora do repositório. - Registre o código de cada desconexão. Sem o log, você adivinha. Com ele, o diagnóstico leva um minuto.
- Reconecte com espera, não em loop. Tentativas imediatas e infinitas só enchem o log e escondem a causa.
- Use o celular principal de vez em quando. Abra o WhatsApp nele ao menos a cada duas semanas.
- Não trate bot não oficial como garantido. Bibliotecas não oficiais podem quebrar quando o WhatsApp muda o protocolo, e usá-las contra os Termos de Serviço é risco seu. Para uso comercial, compare com a Cloud API oficial em Baileys, whatsapp-web.js ou Cloud API: ela usa webhook e token, sem depender de sessão de aparelho vinculado.
Como fazer isso na Square Cloud#
A Square Cloud é hospedagem self-service: você sobe o bot, escolhe a memória e controla o código. Você pode hospedar bots de WhatsApp feitos com Baileys, WPPConnect, whatsapp-web.js ou a Cloud API oficial. A pasta de autenticação fica no disco da aplicação, que persiste entre restarts e deploys, então a sessão continua conectada. Um novo ZIP sobrescreve só os arquivos que estão nele: deixe a pasta de autenticação fora do ZIP para não substituí-la.
Isso elimina a causa mais comum do QR repetido: a sessão que some a cada reinício. Os containers ficam sempre ligados, e o reinício automático, que vem ligado no deploy pelo painel, traz o processo de volta quando ele encerra com erro. Por isso o exemplo sai com código 0 quando a sessão é inválida. Você acompanha os códigos de desconexão nos logs em tempo real do painel ou da CLI. Cada aplicação de fundo, como um bot, tem no mínimo 256 MB de RAM; se usar whatsapp-web.js com Chromium, reserve mais memória.
Defina AUTH_DIR e WA_PHONE nas variáveis de ambiente da aplicação. A regra de uma instância por sessão continua valendo: ao subir o bot, desligue o que roda no seu PC. Veja os detalhes em hospedagem de bots de WhatsApp na Square Cloud.
Hospedagem de bots
Seu bot online 24/7, com reinício automático
Perguntas frequentes
Por que meu bot de WhatsApp pede QR code toda vez que reinicia?
Porque a pasta de autenticação não sobrevive ao reinício. Isso acontece em disco efêmero, em redeploy que recria o container ou quando o código aponta para uma pasta diferente a cada execução. Salve a sessão em um caminho persistente.
O que significa o erro 401 loggedOut no Baileys?
O WhatsApp encerrou a sessão deste aparelho vinculado. Costuma ser porque alguém removeu o aparelho em Dispositivos conectados ou porque o celular principal ficou mais de 14 dias sem uso. Reconectar com as mesmas credenciais não adianta: é preciso apagar a pasta e parear de novo.
Posso rodar o mesmo bot no meu PC e no servidor ao mesmo tempo?
Não com a mesma sessão. A segunda conexão derruba a primeira com o código 440 (connectionReplaced), e as duas ficam se expulsando se cada uma reconectar sozinha. Use uma sessão por instância.
O bot de WhatsApp precisa que o celular fique ligado?
Os aparelhos vinculados funcionam sem o celular online, mas são desconectados se o celular principal ficar mais de 14 dias sem uso. Abrir o WhatsApp no celular de vez em quando basta.
Mais em Bots
Ver todos os 33 artigos- Quanto custa hospedar um bot do Discord?O custo de hospedar um bot do Discord depende de RAM, tempo online, banco de dados e serviços externos. Veja como estimar o seu e onde o gasto aparece.
- Rodar bot no celular (Termux) ou no PC vs hospedar: o que mudaUm bot no PC ou no celular (Termux) fica offline quando o aparelho desliga, dorme ou perde a rede. Compare as três opções e veja quando cada uma serve.
- Como deixar um bot do Discord online 24/7Para deixar um bot do Discord online 24/7, rode o processo numa máquina sempre ligada com reinício automático. Veja PC, VPS com pm2 ou systemd e hospedagem.
- Por que meu bot do Discord fica offline (e como resolver)Bot do Discord offline quase sempre é processo caído, token inválido, intent não habilitada ou falta de memória. Veja como diagnosticar cada causa e corrigir.