WhatsApp API Error Handling: Troubleshooting

Panduan troubleshooting error WhatsApp API. Common errors, solutions, dan best practices. Developer debugging guide!

WhatsApp API Error Handling
WhatsApp API Error Handling

Error itu pasti terjadi!

Yang penting adalah bagaimana handle error dengan baik supaya aplikasi tetap reliable.


Common Errors & Solutions

1. Connection Errors

Error: Connection closed
Error: Connection lost
Error: Timed out

Penyebab:

  • Internet tidak stabil
  • WhatsApp server down
  • Session expired

Solusi:

javascript

sock.ev.on('connection.update', (update) => {
    const { connection, lastDisconnect } = update;
    
    if (connection === 'close') {
        const statusCode = lastDisconnect?.error?.output?.statusCode;
        
        // Auto reconnect kecuali logged out
        if (statusCode !== DisconnectReason.loggedOut) {
            console.log('Reconnecting in 5 seconds...');
            setTimeout(() => startBot(), 5000);
        }
    }
});

2. Authentication Errors

Error: Not authorized
Error: Invalid credentials
Error: Session expired

Penyebab:

  • Session invalid
  • Logged out dari HP
  • Auth file corrupt

Solusi:

javascript

// Delete auth dan re-scan
const fs = require('fs');

function resetAuth() {
    if (fs.existsSync('./auth_info')) {
        fs.rmSync('./auth_info', { recursive: true });
    }
    console.log('Auth reset. Scan QR lagi.');
    startBot();
}

// Trigger saat auth error
if (statusCode === DisconnectReason.loggedOut) {
    resetAuth();
}

3. Rate Limit Errors

Error: Rate limit exceeded
Error: Too many requests
Error Code: 80007

Penyebab:

  • Kirim terlalu cepat
  • Volume terlalu tinggi

Solusi:

javascript

const queue = [];
let isProcessing = false;

async function sendWithQueue(to, message) {
    queue.push({ to, message });
    processQueue();
}

async function processQueue() {
    if (isProcessing || queue.length === 0) return;
    
    isProcessing = true;
    
    while (queue.length > 0) {
        const { to, message } = queue.shift();
        
        try {
            await sock.sendMessage(to, message);
        } catch (error) {
            if (isRateLimitError(error)) {
                // Put back in queue and wait
                queue.unshift({ to, message });
                await sleep(30000); // Wait 30 seconds
            }
        }
        
        await sleep(3000); // 3 second delay between messages
    }
    
    isProcessing = false;
}

4. Invalid Number

Error: Number not registered on WhatsApp
Error: Invalid phone number format

Penyebab:

  • Nomor tidak terdaftar di WA
  • Format nomor salah

Solusi:

javascript

async function validateNumber(phone) {
    try {
        const [result] = await sock.onWhatsApp(phone);
        return result?.exists || false;
    } catch {
        return false;
    }
}

async function safeSend(phone, message) {
    const isValid = await validateNumber(phone);
    
    if (!isValid) {
        console.log(`Invalid number: ${phone}`);
        return { success: false, reason: 'invalid_number' };
    }
    
    await sock.sendMessage(`${phone}@s.whatsapp.net`, message);
    return { success: true };
}

5. Media Errors

Error: Media upload failed
Error: File too large
Error: Unsupported media type

Penyebab:

  • File terlalu besar
  • Format tidak didukung
  • Upload timeout

Solusi:

javascript

const MAX_FILE_SIZE = 16 * 1024 * 1024; // 16MB

async function sendMediaSafe(to, filePath, type) {
    const stats = fs.statSync(filePath);
    
    if (stats.size > MAX_FILE_SIZE) {
        throw new Error('File too large. Max 16MB.');
    }
    
    const supportedTypes = {
        image: ['.jpg', '.jpeg', '.png', '.gif', '.webp'],
        video: ['.mp4', '.3gp'],
        audio: ['.mp3', '.ogg', '.m4a'],
        document: ['.pdf', '.doc', '.docx', '.xls', '.xlsx']
    };
    
    const ext = path.extname(filePath).toLowerCase();
    
    if (!supportedTypes[type]?.includes(ext)) {
        throw new Error(`Unsupported ${type} format: ${ext}`);
    }
    
    // Send with retry
    return await sendWithRetry(to, {
        [type]: fs.readFileSync(filePath)
    });
}

6. Cloud API Errors

json

{
    "error": {
        "message": "(#131030) Recipient phone number not in allowed list",
        "code": 131030
    }
}

Common Cloud API Error Codes:

CodeMeaningSolution
131030Not in allowed listAdd to test numbers
131031Business eligibilityVerify business
131047Re-engagement requiredSend template first
131051Unsupported messageCheck message format
80007Rate limitSlow down
190Access token expiredRefresh token

Error Handling Pattern

Global Error Handler:

javascript

process.on('uncaughtException', (error) => {
    console.error('Uncaught Exception:', error);
    // Log to monitoring service
    logError(error);
    // Don't exit, try to recover
});

process.on('unhandledRejection', (reason, promise) => {
    console.error('Unhandled Rejection:', reason);
    logError(reason);
});

Try-Catch Wrapper:

javascript

async function safeExecute(fn, fallback) {
    try {
        return await fn();
    } catch (error) {
        console.error('Error:', error.message);
        logError(error);
        return fallback;
    }
}

// Usage
const response = await safeExecute(
    () => getAIResponse(message),
    'Maaf, terjadi kesalahan. Coba lagi nanti.'
);

Retry with Backoff:

javascript

async function retryWithBackoff(fn, maxRetries = 3, baseDelay = 1000) {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
            return await fn();
        } catch (error) {
            if (attempt === maxRetries) {
                throw error;
            }
            
            const delay = baseDelay * Math.pow(2, attempt - 1);
            console.log(`Attempt ${attempt} failed. Retrying in ${delay}ms...`);
            await sleep(delay);
        }
    }
}

// Usage
await retryWithBackoff(() => sock.sendMessage(to, message));

Logging Best Practices

javascript

const winston = require('winston');

const logger = winston.createLogger({
    level: 'info',
    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' })
    ]
});

// Log errors with context
function logError(error, context = {}) {
    logger.error({
        message: error.message,
        stack: error.stack,
        ...context,
        timestamp: new Date().toISOString()
    });
}

// Usage
try {
    await sendMessage(to, message);
} catch (error) {
    logError(error, { to, messageType: 'text' });
}

Health Monitoring

javascript

const healthStatus = {
    connected: false,
    lastMessage: null,
    errorCount: 0,
    uptime: Date.now()
};

sock.ev.on('connection.update', (update) => {
    healthStatus.connected = update.connection === 'open';
});

sock.ev.on('messages.upsert', () => {
    healthStatus.lastMessage = Date.now();
});

// Health check endpoint
app.get('/health', (req, res) => {
    const healthy = healthStatus.connected && 
                    (Date.now() - healthStatus.lastMessage < 300000); // 5 min
    
    res.status(healthy ? 200 : 503).json({
        status: healthy ? 'healthy' : 'unhealthy',
        ...healthStatus,
        uptime: Math.floor((Date.now() - healthStatus.uptime) / 1000)
    });
});

FAQ

Bagaimana debug error yang tidak jelas?

Enable verbose logging, check network, dan test dengan minimal code untuk isolate issue.

Kapan harus restart vs reconnect?

Reconnect untuk connection issues. Restart untuk auth issues atau memory leaks.

Perlu monitoring?

Ya! Gunakan tools seperti PM2, Sentry, atau custom health checks.


Kesimpulan

Good error handling = Reliable bot!

PracticeBenefit
Try-catchPrevent crashes
Retry logicHandle transient errors
LoggingDebug & audit
MonitoringProactive alerts

Expect errors, handle gracefully!

Build Reliable Bot →


Artikel Terkait