Appearance
Error Handling Examples
This page demonstrates best practices for handling errors and edge cases when using the Urban Sky SDK.
Basic Error Handling
JavaScript
javascript
// Load the SDK
const response = await fetch('https://sdk.atmosys.com/runtime/js/current/loader.js')
eval(await response.text())
const sdk = await UrbanSkySDK.init({
apiToken: 'your-api-token-here',
debug: true
})
// Handle connection errors
sdk.on('error', (error) => {
console.error('SDK Error:', error)
switch (error.code) {
case 'AUTH_INVALID_TOKEN':
console.error('❌ Invalid API token')
// Stop trying to reconnect
break
case 'AUTH_INSUFFICIENT_PERMISSIONS':
console.error('❌ Token lacks SDK permissions')
// Check token permissions in dashboard
break
case 'CONNECTION_FAILED':
console.error('❌ Connection failed - will retry')
// SDK will auto-retry
break
case 'SERVICE_UNAVAILABLE':
console.error('❌ Service temporarily unavailable')
// Implement exponential backoff
break
default:
console.error('❌ Unknown error:', error.message)
}
})
// Handle connection state changes
sdk.on('connected', () => {
console.log('✅ Connected to Urban Sky')
})
sdk.on('disconnected', () => {
console.log('⚠️ Disconnected from Urban Sky')
})
// Connect with error handling
try {
await sdk.connect()
} catch (error) {
console.error('Failed to connect:', error)
// Handle initial connection failure
}Python
python
import asyncio
import logging
import requests
# Load the SDK
exec(requests.get('https://sdk.atmosys.com/runtime/py/current/loader.py').text)
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
async def main():
# Initialize and connect
sdk = await UrbanSkySDK.init({
'apiToken': 'your-api-token-here'
})
# Error event handler
def on_error(error):
if isinstance(error, dict):
error_code = error.get('error', 'UNKNOWN')
error_message = error.get('message', str(error))
else:
error_code = 'UNKNOWN'
error_message = str(error)
logger.error(f"SDK Error: {error_code} - {error_message}")
if error_code == 'AUTH_INVALID_TOKEN':
logger.error("❌ Invalid API token")
elif error_code == 'AUTH_INSUFFICIENT_PERMISSIONS':
logger.error("❌ Token lacks SDK permissions")
elif error_code == 'CONNECTION_FAILED':
logger.error("❌ Connection failed - will retry")
# SDK will auto-retry
elif error_code == 'SERVICE_UNAVAILABLE':
logger.error("❌ Service temporarily unavailable")
else:
logger.error(f"❌ Unknown error: {error_message}")
# Connection state handlers
def on_connected():
logger.info("✅ Connected to Urban Sky")
def on_disconnected():
logger.warning("⚠️ Disconnected from Urban Sky")
# Register event handlers
sdk.on('error', on_error)
sdk.on('connected', on_connected)
sdk.on('disconnected', on_disconnected)
asyncio.run(main())Simple Retry Logic
For basic retry functionality when connections fail:
javascript
async function initializeWithRetry(config, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
const sdk = await UrbanSkySDK.init(config)
console.log('✅ Connected successfully')
return sdk
} catch (error) {
console.error(`Attempt ${attempt} failed: ${error.message}`)
// Don't retry on authentication errors
if (error.code === 'AUTH_INVALID_TOKEN' || error.code === 'AUTH_INSUFFICIENT_PERMISSIONS') {
console.error('❌ Authentication failed - not retrying')
throw error
}
if (attempt < maxAttempts) {
const delay = attempt * 2000 // Simple backoff: 2s, 4s, 6s
console.log(`Retrying in ${delay}ms...`)
await new Promise(resolve => setTimeout(resolve, delay))
}
}
}
console.error('❌ All connection attempts failed')
return null
}
// Usage
const sdk = await initializeWithRetry({ apiToken: 'your-token' })
if (!sdk) {
console.error('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 'balloon_id' not in update or 'devices' not in update:
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
- Always implement error handlers - Don't let errors crash your application
- Log errors appropriately - Include context for debugging
- Use the SDK's automatic reconnection - Don't implement your own unless necessary
- Handle authentication errors differently - These require user action
- Implement data validation - Verify data structure before processing
Getting Help
If you encounter persistent errors:
- Check the error code and message
- Verify your API token is valid
- Ensure you have a stable internet connection
- 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
Next Steps
- Best Practices - Production-ready patterns
- JavaScript SDK - Full JavaScript API reference
- Python SDK - Full Python API reference
- Balloon Updates Examples - Working with balloon data