Skip to content
WhatIsUp.dev

Solução de problemas

Quebras comuns e como destravá-las.

"O QR nunca aparece"

Sintomas. GET /v1/channels/:id/qr retorna 200 com corpo vazio, ou o painel de QR do dashboard fica em branco.

Causas (em ordem de probabilidade):

  1. O canal já está em qr_required e a string do QR expirou. As strings de QR rotacionam a cada ~30s. O gerenciador de sessão gera uma nova e re-emite um evento qr.updated. Espere uma rotação.
  2. O WhatsApp pode aplicar rate limit a uma sessão. Recriar sessões repetidamente para o mesmo número dispara limites temporários. Espere 5–10 minutos.
  3. MAX_SESSIONS_PER_WORKER excedido. O backend rejeita a criação de novos sockets além desse teto (padrão 50). Cheque o /readyz — ele mostra a contagem.

"sessionInvalidated depois de um pareamento bem-sucedido"

O WhatsApp explicitamente nos disse que a sessão está morta. Razões mais comuns:

  • O usuário abriu o WhatsApp Web num navegador e essa sessão derrubou a nossa (só uma sessão Web por número).
  • O usuário desvinculou o aparelho manualmente em Aparelhos conectados no celular.
  • O número foi logado a partir de uma instalação nova do WhatsApp em outro celular.

O que fazer. O auth-state é apagado automaticamente; o canal vai para disconnected. Faça uma nova busca de QR. Se você vê isso repetidamente para o mesmo número, é quase sempre uma situação de "duas sessões Web" — garanta que ninguém está abrindo web.whatsapp.com com o mesmo número.

"429 rate_limited"

O token bucket por cliente está vazio. Padrões: burst de 60, 1 req/seg sustentado.

O que fazer.

  • Respeite o header Retry-After. Ele te diz quando o bucket vai ter um token.
  • Se você está batendo nisso por uma carga sustentada (não um burst), fale com a gente — a gente aumenta o seu limite.
  • Não fragmente entre várias chaves de API para escapar do limite; o bucket é por cliente, não por chave.

"O webhook nunca chega"

Passe por este checklist:

  1. A URL do endpoint é de DNS público? localhost e RFC1918 são rejeitados na criação. (Use ngrok para dev local.)
  2. Seu endpoint está retornando 2xx? Cheque GET /v1/webhook-deliveries?status=failedlast_error e last_response_status te dizem o que a gente viu.
  3. Você pausou a fila? Se o seu endpoint ficou fora do ar, o worker pode ter passado na sua frente e queimado o orçamento de retentativas. Entregas que falharam além da tentativa 6 não são re-tentadas automaticamente.
  4. Você está filtrando no servidor? Se você definiu events: ['message.received'] no endpoint, não vai receber eventos channel.connected — por design.

"A assinatura do webhook não verifica"

Principais culpados:

  • Você está verificando contra um corpo parseado/reserializado. A assinatura é sobre os bytes brutos. No Express, capture-os com verify: (req, res, buf) => { req.rawBody = buf } no parser JSON.
  • Deriva de relógio. O servidor impõe uma tolerância de timestamp de 5 minutos. Se o relógio do host do seu endpoint estiver mais que isso do tempo real, todo webhook falha. Rode NTP.
  • Segredo errado. Cada endpoint tem seu próprio segredo de assinatura. Se você tem vários endpoints, garanta que está verificando com o que casa com X-WhatIsUp-Endpoint-Id.

"O dashboard diz que meu canal está connected mas as mensagens não saem"

Confira o óbvio antes de ir mais fundo:

  1. Você está usando o channel_id certo em POST /v1/channels/:id/messages? É fácil copiar o errado.
  2. O destinatário to é um MSISDN com código do país, sem +, sem espaços?
  3. Olhe o log de auditoria (aba Atividade no dashboard). Todo envio deixa uma linha.

Se os três estão certos, o problema é a jusante da API:

  • O envio foi enfileirado mas o socket do WhatsApp caiu antes de a mensagem sair. Cheque o /readyz — se o probe de saúde da conexão com o WhatsApp está falhando, a sessão está em mau estado mesmo que a linha diga connected.
  • O envio bateu num rate limit do lado do WhatsApp (separado do nosso limitador). Esses aparecem como webhooks message.failed com error.code: rate_limited.

"Reiniciar o backend perdeu minhas sessões"

O auth-state deveria sobreviver a reinícios. Se não sobreviveu:

  • Filesystem efêmero. Containers sem um volume persistente em data/sessions/ perdem o auth-state a cada redeploy. Monte um volume.
  • Permissão incompatível. Se o volume pertence a um uid diferente do processo Node, o gateway falha silenciosamente ao ler o estado existente e cai de volta para "pareamento novo". Cheque as permissões do arquivo.

Onde conseguir ajuda

  • O log de auditoria (audit_events no dashboard) registra toda ação que muda estado.
  • O /readyz faz verificações profundas: transação no DB, ping no Redis, probe da conexão com o WhatsApp.
  • Abra uma issue em github.com/aneps/zappi — inclua o correlation_id do header da resposta se você tiver um.