> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runanywhere.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Handle SDK errors gracefully

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`:

```swift theme={null}
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

```swift theme={null}
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

```swift theme={null}
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

```swift theme={null}
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

```swift theme={null}
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

```swift theme={null}
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:

```swift theme={null}
// 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

```swift theme={null}
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

```swift theme={null}
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

```swift theme={null}
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

```swift theme={null}
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

```swift theme={null}
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:

```swift theme={null}
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

<AccordionGroup>
  <Accordion title="Always catch SDKError" icon="shield">
    Catch `SDKError` specifically to access detailed error information.
  </Accordion>

  <Accordion title="Provide user-friendly messages" icon="message">
    Use `recoverySuggestion` when available, or map error codes to friendly messages.
  </Accordion>

  <Accordion title="Log errors for debugging" icon="bug">
    Log full error details including stack traces in development builds.
  </Accordion>

  <Accordion title="Implement recovery" icon="rotate">
    Where possible, implement automatic recovery (retries, fallbacks).
  </Accordion>
</AccordionGroup>

<CardGroup cols={2}>
  <Card title="Configuration" icon="gear" href="/swift/configuration">
    SDK configuration →
  </Card>

  <Card title="Best Practices" icon="lightbulb" href="/swift/best-practices">
    Performance tips →
  </Card>
</CardGroup>
