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.
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)
10.3 Upload vs Link
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:
- Verificar logs do servidor
- Testar webhook com curl/Postman
- Verificar formato do payload
- Confirmar credenciais/tokens
- Testar com ngrok localmente
- Verificar rate limits
- Checar status da plataforma (status.fb.com)
Sakaguchi IA - Inteligencia Artificial para Empresas Brasileiras