═══════════════════════════════════════════════════════════════════════════════ ARCADIA GAME SDK - DEVELOPER DOCUMENTATION ═══════════════════════════════════════════════════════════════════════════════ Document: Error Handling Generated: 2/13/2026, 7:46:03 PM Version: 1.0.0 ═══════════════════════════════════════════════════════════════════════════════ Error Handling Guide ══════════════════════════════════════════════════════════════════════ This guide covers all error types, when they occur, and how to handle them properly. Error Types ════════════════════════════════════════════════════════════ The SDK uses specific error classes for different scenarios, making error handling straightforward. Error Class Hierarchy ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ArcadiaSDKError (base class) ├── WalletNotConnectedError ├── PaymentFailedError ├── TimeoutError ├── InvalidConfigError ├── NotInIframeError ├── InvalidAmountError └── InvalidTokenError ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Error Types ════════════════════════════════════════════════════════════ WalletNotConnectedError ══════════════════════════════════════════════════ When it occurs: • Calling [getWalletAddress()] when wallet is not connected • Attempting payment operations without a connected wallet • Wallet disconnects during an operation Error code: [WALLET_NOT_CONNECTED] Example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { WalletNotConnectedError } from '@arcadiasol/sdk'; try { const address = await arcadia.getWalletAddress(); } catch (error) { if (error instanceof WalletNotConnectedError) { showMessage('Please connect your wallet in Arcadia'); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ const walletAddress = await arcadia.getWalletAddress(); if (!walletAddress) { // Wallet not connected - show prompt showWalletConnectionPrompt(); return; } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PaymentFailedError ══════════════════════════════════════════════════ When it occurs: • Transaction is rejected by user • Transaction fails on blockchain • Insufficient funds • Network errors • Developer wallet not configured Error code: [PAYMENT_FAILED] Properties: • [message] - Error message • [txSignature] - Transaction signature (if available) Example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { PaymentFailedError } from '@arcadiasol/sdk'; try { const result = await arcadia.payment.payToPlay(0.5, 'SOL'); } catch (error) { if (error instanceof PaymentFailedError) { console.error('Payment failed:', error.message); if (error.txSignature) { console.log('Transaction:', error.txSignature); } showError('Payment failed: ' + error.message); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ async function processPayment(amount: number) { try { const result = await arcadia.payment.payToPlay(amount, 'SOL'); return result; } catch (error) { if (error instanceof PaymentFailedError) { // Check specific error message if (error.message.includes('insufficient funds')) { showError('Insufficient balance. Please add funds to your wallet.'); } else if (error.message.includes('user rejected')) { showError('Payment cancelled'); } else { showError('Payment failed: ' + error.message); } return null; } throw error; } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ TimeoutError ══════════════════════════════════════════════════ When it occurs: • Request to parent window times out • Network issues prevent communication • Parent window is unresponsive Error code: [TIMEOUT] Example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { TimeoutError } from '@arcadiasol/sdk'; try { const address = await arcadia.getWalletAddress(); } catch (error) { if (error instanceof TimeoutError) { showError('Request timed out. Please try again.'); // Retry logic setTimeout(() => retryGetWalletAddress(), 1000); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ async function getWalletAddressWithRetry(maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await arcadia.getWalletAddress(); } catch (error) { if (error instanceof TimeoutError && i < maxRetries - 1) { await new Promise(resolve => setTimeout(resolve, 1000 (i + 1))); continue; } throw error; } } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ InvalidConfigError ══════════════════════════════════════════════════ When it occurs: • [gameId] is missing or empty • Invalid configuration values Error code: [INVALID_CONFIG] Example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { InvalidConfigError } from '@arcadiasol/sdk'; try { const arcadia = new ArcadiaSDK({ gameId: '', // Invalid - empty string }); } catch (error) { if (error instanceof InvalidConfigError) { console.error('Invalid SDK configuration:', error.message); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ function createSDK(gameId: string) { if (!gameId || gameId.trim().length === 0) { throw new Error('gameId is required'); } try { return new ArcadiaSDK({ gameId }); } catch (error) { if (error instanceof InvalidConfigError) { console.error('SDK configuration error:', error.message); throw new Error('Failed to initialize SDK'); } throw error; } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ NotInIframeError ══════════════════════════════════════════════════ When it occurs: • Calling SDK methods outside of Arcadia's iframe • Testing SDK in standalone environment Error code: [NOT_IN_IFRAME] Example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { NotInIframeError } from '@arcadiasol/sdk'; try { const result = await arcadia.payment.payToPlay(0.5, 'SOL'); } catch (error) { if (error instanceof NotInIframeError) { console.warn('SDK must run in Arcadia iframe'); // Fallback for testing useMockPayment(); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ if (!arcadia.isInIframe()) { console.warn('SDK is not running in iframe - some features may not work'); // Use mock or test mode } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ InvalidAmountError ══════════════════════════════════════════════════ When it occurs: • Payment amount is 0 or negative • Payment amount is not a number • Payment amount is NaN Error code: [INVALID_AMOUNT] Example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { InvalidAmountError } from '@arcadiasol/sdk'; try { await arcadia.payment.payToPlay(-1, 'SOL'); // Invalid } catch (error) { if (error instanceof InvalidAmountError) { showError('Payment amount must be greater than 0'); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ function validateAmount(amount: number): boolean { if (typeof amount !== 'number' || isNaN(amount) || amount <= 0) { showError('Invalid payment amount'); return false; } return true; } const amount = parseFloat(userInput); if (validateAmount(amount)) { await arcadia.payment.payToPlay(amount, 'SOL'); } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ InvalidTokenError ══════════════════════════════════════════════════ When it occurs: • Token type is not 'SOL' or 'USDC' • Token type is invalid Error code: [INVALID_TOKEN] Example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { InvalidTokenError } from '@arcadiasol/sdk'; try { await arcadia.payment.payToPlay(0.5, 'BTC'); // Invalid } catch (error) { if (error instanceof InvalidTokenError) { showError('Invalid token. Use SOL or USDC'); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Handling: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ function validateToken(token: string): token is 'SOL' | 'USDC' { return token === 'SOL' || token === 'USDC'; } const token = userSelectedToken; if (validateToken(token)) { await arcadia.payment.payToPlay(amount, token); } else { showError('Invalid token type'); } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Error Handling Patterns ════════════════════════════════════════════════════════════ Pattern 1: Try-Catch with Type Checking ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import { WalletNotConnectedError, PaymentFailedError, TimeoutError, } from '@arcadiasol/sdk'; try { const result = await arcadia.payment.payToPlay(0.5, 'SOL'); // Success } catch (error) { if (error instanceof WalletNotConnectedError) { showMessage('Please connect your wallet'); } else if (error instanceof PaymentFailedError) { showError('Payment failed: ' + error.message); } else if (error instanceof TimeoutError) { showError('Request timed out. Please try again.'); } else { showError('An unexpected error occurred'); console.error('Unknown error:', error); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Pattern 2: Error Handler Utility ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ class ErrorHandler { static handle(error: unknown): void { if (error instanceof WalletNotConnectedError) { this.showWalletPrompt(); } else if (error instanceof PaymentFailedError) { this.showPaymentError(error); } else if (error instanceof TimeoutError) { this.showTimeoutError(); } else if (error instanceof InvalidAmountError) { this.showAmountError(); } else if (error instanceof InvalidTokenError) { this.showTokenError(); } else { this.showGenericError(error); } } private static showWalletPrompt() { // Show wallet connection UI } private static showPaymentError(error: PaymentFailedError) { // Show payment error with details console.error('Payment failed:', error.message); if (error.txSignature) { console.log('Transaction:', error.txSignature); } } private static showTimeoutError() { // Show timeout message } private static showAmountError() { // Show amount validation error } private static showTokenError() { // Show token validation error } private static showGenericError(error: unknown) { // Show generic error console.error('Error:', error); } } // Usage try { await arcadia.payment.payToPlay(0.5, 'SOL'); } catch (error) { ErrorHandler.handle(error); } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Pattern 3: Retry Logic ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ async function payToPlayWithRetry( amount: number, maxRetries = 3 ): Promise { for (let i = 0; i < maxRetries; i++) { try { return await arcadia.payment.payToPlay(amount, 'SOL'); } catch (error) { if (error instanceof TimeoutError && i < maxRetries - 1) { // Retry on timeout await new Promise(resolve => setTimeout(resolve, 1000 (i + 1))); continue; } else if (error instanceof PaymentFailedError) { // Don't retry payment failures throw error; } else { // Unknown error - retry if (i < maxRetries - 1) { await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); continue; } throw error; } } } return null; } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Common Error Scenarios ════════════════════════════════════════════════════════════ Wallet Not Connected ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // Always check before operations const walletAddress = await arcadia.getWalletAddress(); if (!walletAddress) { showMessage('Please connect your wallet in Arcadia'); return; } // Or use try-catch try { const result = await arcadia.payment.payToPlay(0.5, 'SOL'); } catch (error) { if (error instanceof WalletNotConnectedError) { showWalletConnectionPrompt(); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Payment Rejected by User ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ try { const result = await arcadia.payment.payToPlay(0.5, 'SOL'); } catch (error) { if (error instanceof PaymentFailedError) { if (error.message.includes('user rejected') || error.message.includes('cancelled')) { // User cancelled - don't show error, just return return; } showError('Payment failed: ' + error.message); } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Insufficient Funds ══════════════════════════════════════════════════ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CODE BLOCK [TYPESCRIPT] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ try { const result = await arcadia.payment.payToPlay(0.5, 'SOL'); } catch (error) { if (error instanceof PaymentFailedError) { if (error.message.includes('insufficient funds') || error.message.includes('insufficient balance')) { showError('Insufficient balance. Please add funds to your wallet.'); } else { showError('Payment failed: ' + error.message); } } } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Debugging Tips ════════════════════════════════════════════════════════════ 1. Check Error Messages - Error messages contain useful information 2. Log Transaction Signatures - Payment errors may include transaction signatures 3. Verify SDK State - Check [isInitialized()] and [isInIframe()] 4. Check Wallet Status - Verify wallet is connected before operations 5. Network Issues - Timeout errors often indicate network problems Next Steps ════════════════════════════════════════════════════════════ • Review API Reference for complete error class documentation • See Examples for error handling patterns • Check Security for security-related error handling ═══════════════════════════════════════════════════════════════════════════════ For the latest documentation, visit: https://arcadia.obeliskprotocol.io/developer For support, email: support@arcadia.com ═══════════════════════════════════════════════════════════════════════════════