Skip to content

Error Handling

Comprehensive guide to handling errors in the Urban Sky SDK.

Error Types

The SDK uses structured error handling with specific error codes to help you handle different scenarios appropriately.

Error Codes

CodeDescriptionRecovery Strategy
INVALID_TOKENAPI token is invalidCheck token with Urban Sky support
AUTHENTICATION_FAILEDAuthentication failedVerify credentials
CONNECTION_LOSTConnection to server lostSDK handles automatic reconnection
NETWORK_ERRORNetwork connectivity issueCheck internet connection
TIMEOUTOperation timed outRetry the operation
RATE_LIMITEDRate limit exceededWait before retrying

Basic Error Handling

Connection Errors

Handle connection failures gracefully:

javascript
const sdk = await UrbanSkySDK.init({
  apiToken: 'your-token',
  baseUrl: 'https://api.atmosys.com'
})

// Handle connection errors
sdk.on('error', (error) => {
  console.error('SDK Error:', error.message)
  
  switch (error.code) {
    case 'INVALID_TOKEN':
      console.error('❌ Invalid API token. Please check your credentials.')
      break
      
    case 'AUTHENTICATION_FAILED':
      console.error('❌ Authentication failed. Contact support.')
      break
      
    case 'CONNECTION_LOST':
      console.log('🔄 Connection lost. SDK will attempt to reconnect...')
      // SDK handles reconnection automatically
      break
      
    case 'NETWORK_ERROR':
      console.error('🌐 Network error. Check your internet connection.')
      break
      
    case 'TIMEOUT':
      console.error('⏱️ Connection timeout.')
      break
      
    case 'RATE_LIMITED':
      console.warn('🚦 Rate limited. Please wait before retrying.')
      break
      
    default:
      console.error('❓ Unknown error:', error.message)
      break
  }
})

console.log('✅ SDK initialized and connected successfully')
python
import requests

# Load the SDK
exec(requests.get('https://sdk.atmosys.com/py/loader.py').text)

sdk = await UrbanSkySDK.init({
    'apiToken': 'your-token',
    'baseUrl': 'https://api.atmosys.com'
})

def on_error(error):
    print(f"SDK Error: {error}")
    
    if error.code == 'INVALID_TOKEN':
        print("❌ Invalid API token. Please check your credentials.")
        
    elif error.code == 'AUTHENTICATION_FAILED':
        print("❌ Authentication failed. Contact support.")
        
    elif error.code == 'CONNECTION_LOST':
        print("🔄 Connection lost. SDK will attempt to reconnect...")
        # SDK handles reconnection automatically
        
    elif error.code == 'NETWORK_ERROR':
        print("🌐 Network error. Check your internet connection.")
        
    elif error.code == 'TIMEOUT':
        print("⏱️ Connection timeout.")
        
    elif error.code == 'RATE_LIMITED':
        print("🚦 Rate limited. Please wait before retrying.")
        
    else:
        print(f"❓ Unknown error: {error}")

sdk.on('error', on_error)

Handling Disconnections

The SDK automatically attempts to reconnect when disconnected. You can monitor the connection status:

javascript
// Track connection state
let isConnected = false

sdk.on('connected', () => {
  isConnected = true
  console.log('✅ Connected to Urban Sky')
})

sdk.on('disconnected', () => {
  isConnected = false
  console.log('❌ Disconnected from Urban Sky')
})

// Check connection before operations
function sendData(data) {
  if (!isConnected) {
    console.warn('Not connected. Data will be queued.')
    return
  }
  
  // Process data
}
python
# Track connection state
is_connected = False

def on_connected():
    global is_connected
    is_connected = True
    print("✅ Connected to Urban Sky")

def on_disconnected():
    global is_connected
    is_connected = False
    print("❌ Disconnected from Urban Sky")

sdk.on('connected', on_connected)
sdk.on('disconnected', on_disconnected)

# Check connection before operations
def send_data(data):
    if not is_connected:
        print("Not connected. Data will be queued.")
        return
    
    # Process data

Error Recovery Patterns

Retry Logic

Implement simple retry logic for transient errors:

javascript
async function connectWithRetry(maxAttempts = 3) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      await sdk.connect()
      console.log('✅ Connected successfully')
      return true
    } catch (error) {
      console.error(`Attempt ${attempt} failed: ${error.message}`)
      
      if (attempt < maxAttempts) {
        const delay = attempt * 2000 // Exponential backoff
        console.log(`Retrying in ${delay}ms...`)
        await new Promise(resolve => setTimeout(resolve, delay))
      }
    }
  }
  
  console.error('❌ All connection attempts failed')
  return false
}

// Usage
const connected = await connectWithRetry()
if (!connected) {
  console.error('Unable to establish connection')
}
python
import asyncio

async def connect_with_retry(max_attempts=3):
    for attempt in range(1, max_attempts + 1):
        try:
            await sdk.connect()
            print("✅ Connected successfully")
            return True
        except Exception as error:
            print(f"Attempt {attempt} failed: {error}")
            
            if attempt < max_attempts:
                delay = attempt * 2  # Exponential backoff
                print(f"Retrying in {delay} seconds...")
                await asyncio.sleep(delay)
    
    print("❌ All connection attempts failed")
    return False

# Usage
connected = await connect_with_retry()
if not connected:
    print("Unable to establish connection")

Handling Data Processing Errors

Implement error boundaries for data processing:

javascript
sdk.on('balloon:update', (update) => {
  try {
    // Process update
    processUpdate(update)
  } catch (error) {
    console.error('Error processing update:', error)
    // Log error but don't crash the application
    logError(error, update)
  }
})

function processUpdate(update) {
  // Validate data
  if (!update.balloonId || !update.devices) {
    throw new Error('Invalid update structure')
  }
  
  // Process each device safely
  update.devices.forEach(device => {
    try {
      processDevice(device)
    } catch (error) {
      console.error(`Error processing device ${device.deviceId}:`, error)
    }
  })
}
python
def on_balloon_update(update):
    try:
        # Process update
        process_update(update)
    except Exception as error:
        print(f"Error processing update: {error}")
        # Log error but don't crash the application
        log_error(error, update)

def process_update(update):
    # Validate data
    if not hasattr(update, 'balloon_id') or not hasattr(update, 'devices'):
        raise ValueError("Invalid update structure")
    
    # Process each device safely
    for device in update.devices:
        try:
            process_device(device)
        except Exception as error:
            print(f"Error processing device {device.device_id}: {error}")

sdk.on('balloon:update', on_balloon_update)

Best Practices

  1. Always implement error handlers - Don't let errors crash your application
  2. Log errors appropriately - Include context for debugging
  3. Use the SDK's automatic reconnection - Don't implement your own unless necessary
  4. Handle authentication errors differently - These require user action
  5. Implement data validation - Verify data structure before processing

Getting Help

If you encounter persistent errors:

  1. Check the error code and message
  2. Verify your API token is valid
  3. Ensure you have a stable internet connection
  4. Contact Urban Sky support at support@atmosys.com with:
    • Your organization name
    • The error code and message
    • When the error occurred
    • Any relevant context about what you were trying to do