Voltar ao blog

15 Erros Comuns ao Configurar Chatbot e Como Resolver

Guia de troubleshooting para os problemas mais frequentes em chatbots: webhooks, timeouts, encoding, rate limits e mais.

RS
Richard Sakaguchi Solution Architect
15 Erros Comuns ao Configurar Chatbot e Como Resolver

Configurou o chatbot e nao funciona? Este guia cobre os 15 erros mais comuns e como resolver cada um.

1. Webhook Nao Recebe Mensagens

Sintoma: Voce envia mensagem pro bot mas o webhook nao recebe nada.

Causas comuns:

1.1 URL nao e HTTPS

A maioria das plataformas exige HTTPS. HTTP simples nao funciona.

Solucao:

# Instalar certbot (Let's Encrypt)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d seudominio.com

1.2 Firewall bloqueando

Verificar:

# Testar se porta esta aberta
curl -I https://seusite.com/webhook

# Ver regras de firewall
sudo ufw status

Solucao:

sudo ufw allow 443
sudo ufw allow 80

1.3 Verificacao do webhook falhou

Meta, Telegram e outras plataformas fazem GET de verificacao antes de enviar mensagens.

Debug:

app.get('/webhook', (req, res) => {
  console.log('Query params:', req.query);  // Debug
  // ... resto do codigo
});

2. Mensagem Enviada Mas Nao Entregue

Sintoma: API retorna sucesso mas mensagem nao chega.

2.1 Numero em formato errado

Errado:

(11) 99999-9999
11999999999
+55 11 99999-9999

Correto:

5511999999999

Funcao de normalizacao:

function normalizePhone(phone) {
  // Remove tudo que nao e numero
  let clean = phone.replace(/\D/g, '');

  // Adiciona 55 se nao tem
  if (!clean.startsWith('55')) {
    clean = '55' + clean;
  }

  // Remove 9 extra se tiver 14 digitos
  if (clean.length === 14 && clean[4] === '9') {
    clean = clean.slice(0, 4) + clean.slice(5);
  }

  return clean;
}

2.2 Numero nao tem WhatsApp

Verificar antes de enviar:

async function checkWhatsAppNumber(phone) {
  const url = `https://graph.facebook.com/v18.0/${phoneNumberId}/contacts`;

  const response = await axios.post(url, {
    blocking: 'wait',
    contacts: [phone],
    force_check: true
  }, {
    headers: { Authorization: `Bearer ${token}` }
  });

  return response.data.contacts[0].status === 'valid';
}

3. Timeout no Webhook

Sintoma: Plataforma marca webhook como falho.

3.1 Processamento muito demorado

Webhook precisa responder em 20 segundos (Meta) ou 10 segundos (Telegram).

Solucao - Responder primeiro, processar depois:

app.post('/webhook', async (req, res) => {
  // Responde IMEDIATAMENTE
  res.sendStatus(200);

  // Processa em background
  setImmediate(async () => {
    try {
      await processMessage(req.body);
    } catch (error) {
      console.error('Erro no processamento:', error);
    }
  });
});

Solucao com fila (recomendado para producao):

const Queue = require('bull');
const messageQueue = new Queue('messages', 'redis://localhost:6379');

app.post('/webhook', (req, res) => {
  res.sendStatus(200);
  messageQueue.add(req.body);
});

messageQueue.process(async (job) => {
  await processMessage(job.data);
});

4. Caracteres Estranhos na Mensagem

Sintoma: Acentos viram simbolos estranhos.

4.1 Encoding errado

Headers corretos:

res.set('Content-Type', 'application/json; charset=utf-8');

Body parser configurado:

app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));

4.2 Banco de dados sem UTF-8

MySQL:

ALTER DATABASE seu_banco CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE mensagens CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Conexao:

const connection = mysql.createConnection({
  charset: 'utf8mb4'
});

5. Rate Limit Excedido

Sintoma: Erro 429 ou mensagens nao enviadas.

5.1 Enviando rapido demais

Implementar rate limiting:

const Bottleneck = require('bottleneck');

const limiter = new Bottleneck({
  reservoir: 80,           // 80 requisicoes
  reservoirRefreshAmount: 80,
  reservoirRefreshInterval: 1000,  // por segundo
  maxConcurrent: 10
});

async function sendMessageSafe(to, text) {
  return limiter.schedule(() => sendMessage(to, text));
}

5.2 Muitas conexoes simultaneas

Pool de conexoes:

const https = require('https');

const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 50,
  maxFreeSockets: 10
});

axios.create({
  httpsAgent: agent
});

6. Mensagens Duplicadas

Sintoma: Bot responde duas ou mais vezes.

6.1 Webhook chamado multiplas vezes

Plataformas reenviam se nao recebem 200 OK rapido.

Solucao - Idempotencia:

const processedMessages = new Set();

app.post('/webhook', (req, res) => {
  res.sendStatus(200);  // Responde rapido

  const messageId = req.body.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.id;

  if (!messageId || processedMessages.has(messageId)) {
    return;  // Ja processou ou invalido
  }

  processedMessages.add(messageId);

  // Limpar cache antigo (evitar memory leak)
  if (processedMessages.size > 10000) {
    const toDelete = [...processedMessages].slice(0, 5000);
    toDelete.forEach(id => processedMessages.delete(id));
  }

  processMessage(req.body);
});

Com Redis (producao):

const redis = require('redis');
const client = redis.createClient();

async function isProcessed(messageId) {
  const exists = await client.exists(`msg:${messageId}`);
  if (exists) return true;

  await client.setEx(`msg:${messageId}`, 3600, '1');  // Expira em 1h
  return false;
}

7. Bot Nao Responde Mensagens de Grupo

Sintoma: Funciona no privado, falha em grupos.

7.1 Falta permissao de grupo

Telegram - BotFather:

/setprivacy -> Disable

7.2 Mensagem nao e direta

Verificar se e mencao ou resposta:

// Telegram
if (message.chat.type !== 'private') {
  // Grupo - verificar se foi mencionado
  const botUsername = 'seu_bot';
  if (!message.text?.includes(`@${botUsername}`)) {
    return;  // Ignorar mensagens nao direcionadas
  }
}

8. Sessao Perdida (Estado do Usuario)

Sintoma: Bot esquece contexto da conversa.

8.1 Estado em memoria

Se o servidor reinicia, perde tudo.

Solucao - Persistir estado:

// Redis
const sessions = {};

async function getSession(userId) {
  let session = await redis.get(`session:${userId}`);
  return session ? JSON.parse(session) : { step: 'inicio' };
}

async function setSession(userId, data) {
  await redis.setEx(`session:${userId}`, 86400, JSON.stringify(data));  // 24h
}

// Uso
app.post('/webhook', async (req, res) => {
  const userId = getUserId(req.body);
  const session = await getSession(userId);

  const newSession = await processWithSession(req.body, session);
  await setSession(userId, newSession);

  res.sendStatus(200);
});

9. Erro de Assinatura/Token

Sintoma: Erro 401 ou 403.

9.1 Token expirado

Tokens temporarios da Meta expiram em 24h.

Solucao: Criar System User e gerar token permanente.

9.2 Assinatura invalida (Telegram)

Verificar assinatura:

const crypto = require('crypto');

function verifyTelegramSignature(body, signature) {
  const secret = crypto
    .createHash('sha256')
    .update(BOT_TOKEN)
    .digest();

  const checkHash = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(body))
    .digest('hex');

  return checkHash === signature;
}

10. Imagens/Arquivos Nao Enviam

Sintoma: Texto funciona, midia falha.

10.1 URL nao e publica

A URL da midia precisa ser acessivel publicamente.

Verificar:

curl -I https://seusite.com/imagem.jpg
# Deve retornar 200 OK

10.2 Formato nao suportado

WhatsApp aceita:

  • Imagem: JPG, PNG (max 5MB)
  • Video: MP4 (max 16MB)
  • Audio: OGG, MP3 (max 16MB)
  • Documento: PDF, DOC, etc (max 100MB)

Se URL nao funciona, faça upload primeiro:

async function uploadMedia(filePath, type) {
  const form = new FormData();
  form.append('file', fs.createReadStream(filePath));
  form.append('messaging_product', 'whatsapp');
  form.append('type', type);

  const response = await axios.post(
    `https://graph.facebook.com/v18.0/${phoneNumberId}/media`,
    form,
    {
      headers: {
        ...form.getHeaders(),
        Authorization: `Bearer ${token}`
      }
    }
  );

  return response.data.id;  // media_id
}

// Enviar usando media_id
async function sendImageById(to, mediaId, caption) {
  return axios.post(url, {
    messaging_product: 'whatsapp',
    to: to,
    type: 'image',
    image: {
      id: mediaId,
      caption: caption
    }
  }, { headers });
}

11. Mensagem Marcada Como Spam

Sintoma: Conta bloqueada ou limitada.

11.1 Enviando sem consentimento

Sempre use opt-in explicito.

11.2 Muitas mensagens de marketing

Mantenha proporcao: 80% utilitarias, 20% marketing.

11.3 Template rejeitado

Nao use linguagem promocional excessiva nos templates.

12. Latencia Alta

Sintoma: Demora segundos pra responder.

12.1 Consultas ao banco lentas

Adicionar indices:

CREATE INDEX idx_user_id ON messages(user_id);
CREATE INDEX idx_created_at ON messages(created_at);

12.2 API externa lenta

Cache respostas:

const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 300 });  // 5 min

async function getProductInfo(productId) {
  const cached = cache.get(`product:${productId}`);
  if (cached) return cached;

  const data = await fetchFromAPI(productId);
  cache.set(`product:${productId}`, data);
  return data;
}

13. Bot Para de Funcionar Sozinho

Sintoma: Funciona por horas/dias e para.

13.1 Memory leak

Monitorar memoria:

setInterval(() => {
  const used = process.memoryUsage();
  console.log(`Heap: ${Math.round(used.heapUsed / 1024 / 1024)}MB`);
}, 60000);

13.2 Conexoes nao fechadas

Fechar conexoes:

// Database
pool.on('error', (err) => {
  console.error('Database error:', err);
});

// HTTP
const agent = new https.Agent({
  keepAlive: true,
  timeout: 30000
});

13.3 Usar process manager

# PM2
npm install -g pm2
pm2 start app.js --name "chatbot"
pm2 save
pm2 startup

14. Logs Confusos

Sintoma: Nao consegue debugar problemas.

14.1 Estruturar logs

const winston = require('winston');

const logger = winston.createLogger({
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

// Uso
logger.info('Mensagem recebida', {
  userId: message.from,
  type: message.type,
  timestamp: new Date()
});

logger.error('Erro ao enviar', {
  error: error.message,
  stack: error.stack,
  to: recipient
});

15. Teste Local Dificil

Sintoma: Precisa deploy pra testar.

15.1 Usar ngrok

# Instalar
npm install -g ngrok

# Expor porta local
ngrok http 3000

# Copiar URL https e configurar no webhook

15.2 Simulador de webhook

// test/webhook.test.js
const request = require('supertest');
const app = require('../src/app');

describe('Webhook', () => {
  it('deve processar mensagem de texto', async () => {
    const payload = {
      object: 'whatsapp_business_account',
      entry: [{
        changes: [{
          field: 'messages',
          value: {
            messages: [{
              from: '5511999999999',
              type: 'text',
              text: { body: 'Oi' }
            }],
            metadata: { phone_number_id: '123' }
          }
        }]
      }]
    };

    const res = await request(app)
      .post('/webhook')
      .send(payload);

    expect(res.status).toBe(200);
  });
});

Checklist de Debug

Quando algo nao funciona:

  1. Verificar logs do servidor
  2. Testar webhook com curl/Postman
  3. Verificar formato do payload
  4. Confirmar credenciais/tokens
  5. Testar com ngrok localmente
  6. Verificar rate limits
  7. Checar status da plataforma (status.fb.com)

Sakaguchi IA - Inteligencia Artificial para Empresas Brasileiras

Gostou do conteudo?

Descubra como implementar IA no seu negocio com uma analise gratuita.

Agendar Analise Gratuita

Pronto para automatizar seu atendimento?

Agende uma analise gratuita e descubra como IA pode transformar seu negocio.

Agendar Analise Gratuita