Skip to main content

Error Handling

Understanding and handling errors in the WhatsApp API.

HTTP Status Codes

CodeStatusDescription
200OKRequest successful
201CreatedResource created successfully
400Bad RequestInvalid parameters or malformed request
401UnauthorizedMissing or invalid API key
403ForbiddenAPI key doesn't have access to this resource
404Not FoundSession or resource not found
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error
503Service UnavailableService temporarily unavailable

Error Response Format

All errors follow this format:

{
"success": false,
"error": "Error message describing what went wrong"
}

Some errors include additional fields:

{
"success": false,
"error": "Rate limit exceeded",
"retryAfter": 60
}

Common Errors

Authentication Errors

Missing API Key

{
"success": false,
"error": "API key required. Please provide an API key via X-API-Key header, Authorization header, or api_key query parameter."
}

Solution: Include API key in request headers.

curl -H "X-API-Key: wask_your_key" http://localhost:3000/sessions/{id}/status

Invalid API Key

{
"success": false,
"error": "Invalid API key"
}

Solution: Verify your API key is correct and active.

Wrong Session Access

{
"success": false,
"error": "This API key can only access its own session"
}

Solution: Use the correct API key for the session, or use an admin key.

Session Errors

Session Not Found

{
"success": false,
"error": "Session not found"
}

Solution: Verify the session ID is correct and the session exists.

Session Not Authenticated

{
"success": false,
"error": "Session not authenticated. Please scan the QR code first using GET /sessions/{id}/qr"
}

Solution: Scan the QR code to authenticate the session.

Session Still Connecting

{
"success": false,
"error": "Session is still connecting. Please wait."
}

Solution: Wait a few seconds and retry.

QR Code Not Ready

{
"success": false,
"error": "QR code not available yet. Session state: starting"
}

Solution: Wait for session state to become qr_ready.

Message Errors

Invalid Phone Number

{
"success": false,
"error": "Invalid phone number format"
}

Solution: Use correct format with country code (e.g., 919876543210).

Number Not on WhatsApp

{
"success": false,
"error": "Number is not registered on WhatsApp"
}

Solution: Verify the number is active on WhatsApp using /check-number endpoint.

Message Too Long

{
"success": false,
"error": "Message text exceeds maximum length"
}

Solution: Split long messages into multiple parts.

Rate Limit Errors

Rate Limit Exceeded

{
"success": false,
"error": "Rate limit exceeded. Please wait 45 seconds before trying again.",
"retryAfter": 45
}

Solution: Wait for the specified time before retrying.

QR Polling Too Fast

{
"success": false,
"error": "Please wait 5 seconds before requesting QR again"
}

Solution: Add delay between QR code requests.

Trial Key Errors

Trial Expired

{
"success": false,
"error": "Trial period has expired"
}

Solution: Convert to paid key or request trial extension.

Number Not Allowed

{
"success": false,
"error": "Trial key can only send to allowed numbers: +919876543210"
}

Solution: Send only to allowed numbers or upgrade to standard key.

Media Errors

Invalid Media URL

{
"success": false,
"error": "Failed to download media from URL"
}

Solution: Verify URL is accessible and returns valid media.

Media Too Large

{
"success": false,
"error": "Media file size exceeds maximum allowed (16MB)"
}

Solution: Compress or resize media before sending.

Error Handling Examples

PHP

<?php
try {
$result = $whatsapp->sendText('919876543210', 'Hello!');
echo "Message sent: " . $result['messageId'];
} catch (Exception $e) {
$error = $e->getMessage();

if (strpos($error, 'Rate limit') !== false) {
// Handle rate limit
error_log("Rate limited, will retry later");
// Add to queue for retry
} elseif (strpos($error, 'not authenticated') !== false) {
// Session needs authentication
error_log("Session not authenticated, please scan QR");
} elseif (strpos($error, 'not found') !== false) {
// Session doesn't exist
error_log("Session not found");
} else {
// Other errors
error_log("Error: " . $error);
}
}

Node.js

try {
const result = await whatsapp.sendText('919876543210', 'Hello!');
console.log('Message sent:', result.messageId);
} catch (error) {
const errorMsg = error.message;

if (errorMsg.includes('Rate limit')) {
// Handle rate limit
console.log('Rate limited, will retry later');
// Add to queue for retry
} else if (errorMsg.includes('not authenticated')) {
// Session needs authentication
console.log('Session not authenticated, please scan QR');
} else if (errorMsg.includes('not found')) {
// Session doesn't exist
console.log('Session not found');
} else {
// Other errors
console.error('Error:', errorMsg);
}
}

Python

try:
result = whatsapp.send_text('919876543210', 'Hello!')
print(f"Message sent: {result['messageId']}")
except Exception as e:
error_msg = str(e)

if 'Rate limit' in error_msg:
# Handle rate limit
print('Rate limited, will retry later')
# Add to queue for retry
elif 'not authenticated' in error_msg:
# Session needs authentication
print('Session not authenticated, please scan QR')
elif 'not found' in error_msg:
# Session doesn't exist
print('Session not found')
else:
# Other errors
print(f"Error: {error_msg}")

Retry Strategies

Exponential Backoff

async function sendWithRetry(whatsapp, to, message, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await whatsapp.sendText(to, message);
} catch (error) {
const isLastAttempt = attempt === maxRetries - 1;
const isRetryable = error.message.includes('Rate limit') ||
error.message.includes('still connecting');

if (isRetryable && !isLastAttempt) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
console.log(`Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}

Conditional Retry

import time

def should_retry(error):
"""Determine if error is retryable"""
retryable_errors = [
'Rate limit',
'still connecting',
'temporarily unavailable',
'timeout'
]
return any(err in str(error) for err in retryable_errors)

def send_with_retry(whatsapp, to, message, max_retries=3):
for attempt in range(max_retries):
try:
return whatsapp.send_text(to, message)
except Exception as e:
if should_retry(e) and attempt < max_retries - 1:
delay = 2 ** attempt
print(f"Retry {attempt + 1}/{max_retries} after {delay}s")
time.sleep(delay)
else:
raise

Error Logging

Structured Logging

const winston = require('winston');

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

try {
await whatsapp.sendText(to, message);
} catch (error) {
logger.error('Failed to send message', {
to,
error: error.message,
timestamp: new Date().toISOString(),
sessionId: whatsapp.sessionId
});
}

Error Monitoring

<?php
class ErrorMonitor {
private $errors = [];

public function recordError($type, $message, $context = []) {
$this->errors[] = [
'type' => $type,
'message' => $message,
'context' => $context,
'timestamp' => date('c')
];

// Send to monitoring service (e.g., Sentry)
$this->sendToMonitoring($type, $message, $context);
}

public function getErrorStats() {
$stats = [];
foreach ($this->errors as $error) {
$type = $error['type'];
$stats[$type] = ($stats[$type] ?? 0) + 1;
}
return $stats;
}

private function sendToMonitoring($type, $message, $context) {
// Send to Sentry, Rollbar, etc.
}
}

Validation

Pre-Send Validation

class MessageValidator {
static validate(to, message) {
const errors = [];

// Validate phone number
if (!/^\d{10,15}$/.test(to.replace(/[+\s-]/g, ''))) {
errors.push('Invalid phone number format');
}

// Validate message length
if (message.length > 4096) {
errors.push('Message exceeds maximum length (4096 characters)');
}

// Validate message not empty
if (!message.trim()) {
errors.push('Message cannot be empty');
}

return {
valid: errors.length === 0,
errors
};
}
}

// Usage
const validation = MessageValidator.validate(to, message);
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
return;
}

await whatsapp.sendText(to, message);

Debugging Tips

Enable Verbose Logging

const axios = require('axios');

// Log all requests
axios.interceptors.request.use(request => {
console.log('Request:', {
method: request.method,
url: request.url,
data: request.data
});
return request;
});

// Log all responses
axios.interceptors.response.use(
response => {
console.log('Response:', response.data);
return response;
},
error => {
console.error('Error:', {
status: error.response?.status,
data: error.response?.data
});
return Promise.reject(error);
}
);

Check Session State

def ensure_session_ready(whatsapp, max_wait=60):
"""Wait for session to be ready"""
import time

start = time.time()
while time.time() - start < max_wait:
status = whatsapp.get_status()
state = status['session']['state']

if state == 'ready':
return True
elif state in ['failed', 'logged_out']:
raise Exception(f"Session in {state} state")

print(f"Session state: {state}, waiting...")
time.sleep(5)

raise Exception("Session not ready after timeout")

# Usage
ensure_session_ready(whatsapp)
result = whatsapp.send_text('919876543210', 'Hello!')

Best Practices

  1. Always Handle Errors - Never ignore exceptions
  2. Implement Retries - For transient errors
  3. Log Errors - For debugging and monitoring
  4. Validate Input - Before making API calls
  5. Check Session State - Before sending messages
  6. Monitor Rate Limits - To avoid hitting limits
  7. Use Timeouts - Prevent hanging requests
  8. Graceful Degradation - Have fallback options