Skip to main content
The RunAnywhere SDK uses a unified error system that provides detailed information for debugging and user-friendly messages for display.

SDKError

All SDK errors are represented by SDKError:
public struct SDKError: Error, LocalizedError, Sendable {
    public let code: ErrorCode           // Error code enum
    public let message: String           // Detailed message
    public let category: ErrorCategory   // Error category
    public let stackTrace: [String]      // Debug stack trace
    public let underlyingError: (any Error)? // Wrapped error

    public var errorDescription: String? { get }
    public var failureReason: String? { get }
    public var recoverySuggestion: String? { get }
}

Error Codes

public enum ErrorCode: String, Sendable {
    // Initialization
    case notInitialized
    case invalidConfiguration
    case invalidAPIKey
    case validationFailed

    // Models
    case modelNotFound
    case modelLoadFailed
    case modelIncompatible

    // Generation
    case generationFailed
    case processingFailed
    case streamingNotSupported

    // Audio
    case emptyAudioBuffer
    case microphonePermissionDenied

    // Network
    case networkUnavailable
    case networkError
    case timeout

    // Storage
    case insufficientStorage
    case insufficientMemory
    case storageError

    // General
    case initializationFailed
    case cancelled
    case invalidState
    case invalidInput
    case notImplemented
    case unknown
}

Error Categories

public enum ErrorCategory: String, Sendable {
    case general
    case stt
    case tts
    case llm
    case vad
    case voiceAgent
    case download
    case fileManagement
    case network
    case authentication
    case security
    case runtime
}

Basic Error Handling

do {
    let result = try await RunAnywhere.generate("Hello")
    print(result.text)
} catch let error as SDKError {
    print("Error: \(error.message)")
    print("Code: \(error.code)")
    print("Category: \(error.category)")

    if let suggestion = error.recoverySuggestion {
        print("Suggestion: \(suggestion)")
    }
} catch {
    print("Unexpected error: \(error)")
}

Handling Specific Errors

By Error Code

do {
    let result = try await RunAnywhere.generate(prompt)
} catch let error as SDKError {
    switch error.code {
    case .notInitialized:
        // SDK not initialized
        showAlert("Please restart the app")

    case .modelNotFound:
        // Model not loaded
        try await RunAnywhere.loadModel("default-model")

    case .modelLoadFailed:
        // Model failed to load
        showAlert("Failed to load AI model. Try redownloading.")

    case .generationFailed:
        // Generation failed
        showAlert("Generation failed. Please try again.")

    case .insufficientMemory:
        // Not enough RAM
        try await RunAnywhere.unloadModel()
        showAlert("Low memory. Some features may be limited.")

    case .networkUnavailable:
        // No network (may be needed for auth)
        showOfflineMode()

    case .timeout:
        // Operation timed out
        showAlert("Request timed out. Please try again.")

    case .cancelled:
        // User cancelled
        break

    default:
        showAlert("An error occurred: \(error.message)")
    }
}

By Category

do {
    let result = try await RunAnywhere.processVoiceTurn(audioData)
} catch let error as SDKError {
    switch error.category {
    case .llm:
        handleLLMError(error)
    case .stt:
        handleSTTError(error)
    case .tts:
        handleTTSError(error)
    case .network:
        handleNetworkError(error)
    case .authentication:
        handleAuthError(error)
    default:
        handleGenericError(error)
    }
}

Error Factory Methods

The SDK provides factory methods for creating errors:
// Create errors programmatically
SDKError.general(.notInitialized, "SDK not initialized")
SDKError.llm(.generationFailed, "Generation failed", underlying: originalError)
SDKError.stt(.modelNotFound, "STT model not found")
SDKError.tts(.processingFailed, "TTS synthesis failed")
SDKError.network(.networkUnavailable, "No internet connection")
SDKError.authentication(.invalidAPIKey, "Invalid API key")

SwiftUI Error Handling

struct ContentView: View {
    @State private var error: SDKError?
    @State private var showError = false
    @State private var response = ""

    var body: some View {
        VStack {
            Text(response)

            Button("Generate") {
                Task { await generate() }
            }
        }
        .alert("Error", isPresented: $showError, presenting: error) { _ in
            Button("OK") { error = nil }
        } message: { error in
            VStack {
                Text(error.message)
                if let suggestion = error.recoverySuggestion {
                    Text(suggestion)
                        .font(.caption)
                }
            }
        }
    }

    func generate() async {
        do {
            let result = try await RunAnywhere.generate("Hello")
            response = result.text
        } catch let sdkError as SDKError {
            error = sdkError
            showError = true
        } catch {
            self.error = SDKError.general(.unknown, error.localizedDescription)
            showError = true
        }
    }
}

Error Recovery Strategies

Retry Logic

func generateWithRetry(
    prompt: String,
    maxRetries: Int = 3
) async throws -> LLMGenerationResult {
    var lastError: Error?

    for attempt in 1...maxRetries {
        do {
            return try await RunAnywhere.generate(prompt)
        } catch let error as SDKError {
            lastError = error

            // Don't retry certain errors
            switch error.code {
            case .notInitialized, .invalidAPIKey, .modelNotFound:
                throw error
            case .timeout, .networkError:
                // Retry with delay
                try await Task.sleep(for: .seconds(Double(attempt)))
            default:
                throw error
            }
        }
    }

    throw lastError ?? SDKError.general(.unknown, "Max retries exceeded")
}

Graceful Degradation

func generateResponse(_ prompt: String) async -> String {
    do {
        let result = try await RunAnywhere.generate(prompt)
        return result.text
    } catch let error as SDKError {
        switch error.code {
        case .modelNotFound:
            return "Please wait while the AI model loads..."
        case .insufficientMemory:
            return "Memory is low. Please close other apps and try again."
        case .timeout:
            return "The request took too long. Please try a shorter prompt."
        default:
            return "I'm having trouble responding right now. Please try again."
        }
    } catch {
        return "An unexpected error occurred."
    }
}

Model Fallback

func generateWithFallback(_ prompt: String) async throws -> String {
    // Try primary model
    do {
        return try await RunAnywhere.chat(prompt)
    } catch let error as SDKError where error.code == .generationFailed {
        // Try smaller model
        try await RunAnywhere.unloadModel()
        try await RunAnywhere.loadModel("llama-3.2-1b-instruct-q4")  // Smaller model
        return try await RunAnywhere.chat(prompt)
    }
}

Logging Errors

func logError(_ error: SDKError) {
    print("""
    === SDK Error ===
    Code: \(error.code.rawValue)
    Category: \(error.category.rawValue)
    Message: \(error.message)
    Suggestion: \(error.recoverySuggestion ?? "None")
    Stack: \(error.stackTrace.joined(separator: "\n"))
    Underlying: \(error.underlyingError?.localizedDescription ?? "None")
    ================
    """)
}

Event-Based Error Handling

Subscribe to error events SDK-wide:
import Combine

class ErrorHandler {
    private var cancellables = Set<AnyCancellable>()

    init() {
        // Subscribe to all errors
        RunAnywhere.events.events
            .compactMap { $0 as? ErrorEvent }
            .sink { event in
                self.handleError(event.error)
            }
            .store(in: &cancellables)
    }

    private func handleError(_ error: Error) {
        // Log to analytics, show UI, etc.
    }
}

Best Practices

Catch SDKError specifically to access detailed error information.
Use recoverySuggestion when available, or map error codes to friendly messages.
Log full error details including stack traces in development builds.
Where possible, implement automatic recovery (retries, fallbacks).