Error Handling

Comprehensive guide to handling errors gracefully and ensuring smooth ad experiences.

â„šī¸ Why Error Handling Matters: Ads can fail for many reasons (network issues, no fill, VAST errors, etc.). Proper error handling ensures your app remains stable and provides fallback options for users.

Error Callback

The onError callback is triggered whenever an error occurs during ad loading or playback:

JavaScript
RewardedAd.init({
    appId: "YOUR_APP_ID",
    apiKey: "YOUR_API_KEY",
    userId: "user_123",
    
    onError: function(error) {
        console.error('❌ Ad Error:', error.message);
        console.error('Error Code:', error.code);
        console.error('Details:', error.details);
        
        // Handle error appropriately
        handleAdError(error);
    }
});

Error Object Structure

TypeScript
{
    code: string,           // Error code (e.g., "NETWORK_ERROR")
    message: string,        // Human-readable error message
    details: object,        // Additional error context
    timestamp: number       // When error occurred
}

Common Error Codes

Error Code Description Common Causes
NETWORK_ERROR Network request failed No internet, timeout, DNS failure
NO_FILL No ads available Low inventory, targeting mismatch
INVALID_CONFIG SDK configuration error Missing appId, apiKey, or userId
RATE_LIMIT Frequency cap exceeded User hit hourly/daily limits
VAST_ERROR VAST XML parsing failed Malformed VAST, unsupported format
MEDIA_ERROR Video playback failed Unsupported format, DRM issues
TIMEOUT Request timed out Slow network, server issues

VAST Error Codes

For VAST ads, additional IAB standard error codes are provided:

Code Description Category
100 XML parsing error VAST Structure
101 VAST schema validation error VAST Structure
102 VAST version not supported VAST Structure
300 General wrapper error VAST Wrapper
400 General linear error Video
401 File not found Video
402 Timeout of media file Video
403 Unsupported media type Video
900 Undefined error General

Error Handling Strategies

1. Basic Error Handler

JavaScript
function handleAdError(error) {
    // Log for debugging
    console.error('Ad Error:', error.code, error.message);
    
    // Show user-friendly message
    const messages = {
        'NETWORK_ERROR': 'Connection issue. Please check your internet.',
        'NO_FILL': 'No ads available right now. Try again later!',
        'RATE_LIMIT': 'You\'ve watched the maximum ads for now.',
        'VAST_ERROR': 'Ad format not supported.',
        'MEDIA_ERROR': 'Video could not be played.',
        'TIMEOUT': 'Request timed out. Please try again.'
    };
    
    const message = messages[error.code] || 'Something went wrong. Please try again.';
    showNotification(message);
    
    // Resume game if it was paused
    resumeGame();
}

2. Retry Logic

JavaScript
let retryCount = 0;
const MAX_RETRIES = 2;

function showAdWithRetry() {
    RewardedAd.showAd({
        rewardPreview: '100 coins',
        onError: function(error) {
            if (error.code === 'NETWORK_ERROR' && retryCount < MAX_RETRIES) {
                retryCount++;
                console.log(`Retrying... (${retryCount}/${MAX_RETRIES})`);
                
                // Retry after delay
                setTimeout(() => {
                    showAdWithRetry();
                }, 2000);
            } else {
                // Max retries reached or non-retryable error
                retryCount = 0;
                handleAdError(error);
            }
        },
        onReward: function() {
            retryCount = 0; // Reset on success
            grantCoins(100);
        }
    });
}

3. Fallback Options

JavaScript
function tryShowAd() {
    RewardedAd.showAd({
        rewardPreview: '100 coins',
        
        onError: function(error) {
            console.error('Ad failed:', error.code);
            
            // Offer alternative reward methods
            showFallbackOptions([
                {
                    label: 'Complete a quest',
                    action: () => showQuests(),
                    icon: 'đŸŽ¯'
                },
                {
                    label: 'Invite a friend',
                    action: () => showInviteScreen(),
                    icon: 'đŸ‘Ĩ'
                },
                {
                    label: 'Purchase coins',
                    action: () => showStore(),
                    icon: '💰'
                }
            ]);
        },
        
        onReward: function() {
            grantCoins(100);
        }
    });
}

4. Error Analytics

JavaScript
class ErrorTracker {
    constructor() {
        this.errors = [];
    }
    
    track(error) {
        this.errors.push({
            code: error.code,
            message: error.message,
            timestamp: Date.now()
        });
        
        // Log to your analytics service
        this.sendToAnalytics(error);
        
        // Check error rate
        this.checkErrorRate();
    }
    
    sendToAnalytics(error) {
        // Send to your analytics platform
        if (window.gtag) {
            gtag('event', 'ad_error', {
                error_code: error.code,
                error_message: error.message
            });
        }
    }
    
    checkErrorRate() {
        // Last 10 attempts
        const recent = this.errors.slice(-10);
        const errorRate = recent.length / 10;
        
        if (errorRate > 0.5) {
            console.warn('âš ī¸ High error rate detected:', errorRate);
            // Maybe disable ads temporarily
        }
    }
    
    getReport() {
        const errorCounts = {};
        this.errors.forEach(e => {
            errorCounts[e.code] = (errorCounts[e.code] || 0) + 1;
        });
        
        console.log('Error Report:', errorCounts);
        return errorCounts;
    }
}

const errorTracker = new ErrorTracker();

RewardedAd.init({
    // ...config
    onError: function(error) {
        errorTracker.track(error);
        handleAdError(error);
    }
});

Complete Error Handler

JavaScript
class AdErrorHandler {
    constructor() {
        this.retryAttempts = 0;
        this.maxRetries = 2;
        this.errorLog = [];
    }
    
    handle(error) {
        // Log error
        this.logError(error);
        
        // Handle based on error type
        switch (error.code) {
            case 'NETWORK_ERROR':
                return this.handleNetworkError(error);
            
            case 'NO_FILL':
                return this.handleNoFill(error);
            
            case 'RATE_LIMIT':
                return this.handleRateLimit(error);
            
            case 'VAST_ERROR':
            case 'MEDIA_ERROR':
                return this.handleMediaError(error);
            
            case 'INVALID_CONFIG':
                return this.handleConfigError(error);
            
            default:
                return this.handleUnknownError(error);
        }
    }
    
    handleNetworkError(error) {
        if (this.retryAttempts < this.maxRetries) {
            this.retryAttempts++;
            console.log(`Network error, retrying... (${this.retryAttempts}/${this.maxRetries})`);
            
            setTimeout(() => {
                RewardedAd.showAd();
            }, 2000);
        } else {
            this.showMessage('Connection issue. Please check your internet and try again.');
            this.retryAttempts = 0;
        }
    }
    
    handleNoFill(error) {
        this.showMessage('No ads available right now. Try again in a moment!');
        this.showFallbackOptions();
    }
    
    handleRateLimit(error) {
        const cooldown = RewardedAd.getCooldownRemaining();
        if (cooldown > 0) {
            this.showMessage(`Please wait ${cooldown} seconds before the next ad.`);
        } else {
            this.showMessage('You\'ve reached the ad limit. Try again later!');
        }
    }
    
    handleMediaError(error) {
        this.showMessage('Ad format not supported. Trying next ad...');
        // SDK will automatically try next ad in mediation waterfall
    }
    
    handleConfigError(error) {
        console.error('âš ī¸ SDK Configuration Error:', error.message);
        this.showMessage('App configuration error. Please contact support.');
        // This is a critical error - log to error tracking service
    }
    
    handleUnknownError(error) {
        console.error('Unknown error:', error);
        this.showMessage('Something went wrong. Please try again.');
    }
    
    logError(error) {
        this.errorLog.push({
            code: error.code,
            message: error.message,
            timestamp: new Date().toISOString()
        });
        
        // Send to error tracking service
        if (window.Sentry) {
            Sentry.captureException(new Error(`Ad Error: ${error.code}`), {
                extra: error
            });
        }
    }
    
    showMessage(text) {
        alert(text); // Replace with your notification system
    }
    
    showFallbackOptions() {
        // Show alternative ways to earn rewards
        console.log('Showing fallback options...');
    }
    
    reset() {
        this.retryAttempts = 0;
    }
    
    getErrorReport() {
        return this.errorLog;
    }
}

// Usage
const errorHandler = new AdErrorHandler();

RewardedAd.init({
    appId: "YOUR_APP_ID",
    apiKey: "YOUR_API_KEY",
    userId: "user_123",
    
    onError: function(error) {
        errorHandler.handle(error);
    },
    
    onReward: function(reward) {
        errorHandler.reset(); // Reset retry count on success
        grantCoins(100);
    },
    
    onClose: function() {
        resumeGame();
    }
});

Best Practices

✅ DO:
  • Always implement onError callback
  • Show user-friendly error messages
  • Log errors to analytics/monitoring service
  • Offer fallback options when ads fail
  • Retry network errors (max 2-3 times)
  • Resume game after errors
  • Test error scenarios during development
âš ī¸ DON'T:
  • Show technical error messages to users
  • Retry indefinitely (max 2-3 attempts)
  • Ignore errors silently
  • Leave game in broken state after errors
  • Retry rate limit errors
  • Expose sensitive error details in production

Testing Error Scenarios

Simulate Errors in Development

JavaScript
// Enable debug mode
RewardedAd.enableDebug();

// Test different error scenarios
function testErrors() {
    // 1. Test network error (disable internet)
    console.log('Test: Disable internet and call showAd()');
    
    // 2. Test no fill (use invalid app ID)
    console.log('Test: Use invalid appId');
    
    // 3. Test rate limit (show 11 ads in an hour)
    console.log('Test: Show ads rapidly');
    
    // 4. Test VAST error (use malformed VAST URL)
    console.log('Test: Use invalid VAST tag');
}

// Monitor all errors
let errorCount = 0;
RewardedAd.init({
    // ...config
    onError: function(error) {
        errorCount++;
        console.error(`Error #${errorCount}:`, error.code, error.message);
    }
});

Error Recovery Checklist

✅ Error Recovery Checklist:
  • â˜‘ī¸ Error logged to console/analytics
  • â˜‘ī¸ User shown friendly message
  • â˜‘ī¸ Game/app resumed (if paused)
  • â˜‘ī¸ Fallback options offered (if applicable)
  • â˜‘ī¸ Retry attempted (for network errors)
  • â˜‘ī¸ UI state reset to normal

Related Topics