Error handling is a fundamental skill for mobile developers. According to HackerOne (2025), 62% of data breaches occur due to unhandled exceptions. Proper error handling not only prevents crashes but also protects user data. Let's explore approaches for iOS, Android, and React Native.
Key Takeaways
Error handling in Swift is built on four key mechanisms: do-catch, throws, guard let, and if-let. Unlike many languages, Swift does not allow uncaught exceptions — every error must be explicitly handled or declared via throws. Error handling is a critical skill for mobile development, directly impacting application stability.
do-catch is the standard block for calling functions marked with throws. Inside do, a function is called with try, and if it throws an error, control transfers to catch. Different error types can be handled via pattern matching. If an error is not handled, it propagates up the stack (Error Propagation). For effective error handling in iOS, use do-catch as the primary mechanism.
Throw is declared in the function signature: func fetchData() throws -> Data. This means the calling code must handle the error via try, try?, or try!. try? converts the error to nil, try! causes a crash on error (use only if you are certain of success). Error handling via throw is mandatory practice in Swift.
Guard let is a construct for early exit from a function if the value is nil. Unlike if-let, guard let requires an exit (return, throw, break) in the else branch. This makes code flatter and more readable — without nested if blocks. If an optional cannot be nil — use force unwrap (!), only when absolutely certain. In a mobile app, guard let helps avoid crashes when handling optional values.
Optional Chaining (user?.address?.city) and nil-coalescing (??) are syntactic sugar for working with optionals without unwrapping. At IT Sectr, we use guard let for validating API input parameters and enforce the team to avoid force unwrap without an explicit comment. An error handler at every level protects against unexpected failures.
Kotlin is the primary language for Android development. It inherits try-catch from Java but adds safer alternatives: the elvis operator, require, check, and sealed class. Error handling in Kotlin is built on a combination of these mechanisms. Unlike Swift, Kotlin does not require handling checked exceptions (all exceptions are unchecked). For error handling in mobile applications on Android, use sealed class as the primary pattern.
Try-catch in Kotlin works as an expression — it returns a value. val result = try { fetchData() } catch (e: Exception) { fallbackValue }. This reduces code. The Elvis operator (?:) is an analogue of nil-coalescing for nullable types: val name = user?.name ?: "Guest". For error handling in mobile applications, try-catch as an expression is the most concise approach.
Sealed class is a powerful tool for modeling success and error states. sealed class NetworkResult { data class Success(val data: T) : NetworkResult(); data class Error(val message: String) : NetworkResult() }. When used in a when expression, the compiler checks branch exhaustiveness. Error handling via sealed class guarantees that no state is left unhandled.
// Sealed class + try-catch — typical pattern for Android
sealed class NetworkResult<out T> {
data class Success<out T>(val data: T) : NetworkResult<T>()
data class Error(val message: String) : NetworkResult<Nothing>()
}
fun fetchUser(id: String): NetworkResult<User> {
return try {
NetworkResult.Success(api.getUser(id))
} catch (e: Exception) {
NetworkResult.Error("Failed: ${e.message}")
}
}
In the example, the sealed class NetworkResult models two states: success with data and error with a message. The fetchUser function returns a result in any case, and the calling code handles both branches via when. This eliminates the possibility of an unhandled error. Error handling via sealed class is the standard for Android development at IT Sectr.
Result is a built-in Kotlin type for representing the outcome of an operation that may fail. It forces handling success and failure via fold, getOrThrow, or map. Result is useful in asynchronous chains (coroutines). Error handling with Result is a standard for mobile development in Kotlin.
Either is a functional type from the Arrow library that allows returning a value of one of two types (Left — error, Right — success). Unlike Result, Either can contain any user-defined error type. For simple projects, built-in Result is sufficient; for complex ones, use Either from Arrow. The choice of error handling tool depends on project complexity.
Error Propagation is a mechanism where an error propagates up the call stack until it is handled. In Kotlin, this happens by default (unchecked exceptions). In Swift, this only applies to functions marked with throws. With Result and Either, errors do not propagate — they remain in the type, and you must handle them. This makes error handling in mobile applications safer.
| Parameter | iOS (Swift) | Android (Kotlin) |
|---|---|---|
| Basic mechanism | do-catch + throws | try-catch (expression) |
| Optional/Nullable | guard let, if-let, ?? | ?. let, elvis (?:) |
| Functional approach | Result (Swift 5+) | Result, Either (Arrow) |
| Error modeling | Enum: Error | Sealed class |
| Checked exceptions | Yes (throws) | No (all unchecked) |
| Non-fatal | os_log, Crashlytics | Timber, Crashlytics |
The table shows key differences. iOS requires explicit error declaration (throws), making code safer but more verbose. Android relies on developer discipline. At IT Sectr, we use sealed class for Android and throws for iOS — this is the best practice of both platforms for error handling in mobile applications.
Crash reporting is a system for collecting and analyzing application crashes. Crash reporting is an essential part of error handling in production. Without it, you learn about problems from users, which is unacceptable for production. Two main tools: Firebase Crashlytics (free) and Sentry (free for basic use). For error handling in mobile applications, always implement crash reporting from the first release.
Crashlytics is part of Firebase. It automatically collects crashes, groups them by call stack, and shows the number of affected users. It supports logging non-fatal errors via recordException(). Integration: add the SDK to build.gradle (Android) or Podfile (iOS). Crashlytics is the best free tool for error handling when starting a project.
Sentry is a cross-platform error monitoring system. Unlike Crashlytics, Sentry provides detailed tracing (breadcrumbs), performance monitoring, and React Native support. It allows you to view the application state at the moment of error. IT Sectr recommends Sentry for projects that need full control over error handling in mobile development.
Error Boundary is a React component that catches JavaScript errors in the child component tree and displays a fallback UI, preventing a complete app crash. Error Boundary is a key component for error handling in React Native. Use error boundaries for critical screens and navigation. Error handling in mobile applications on React Native requires proper Error Boundary setup at the top level.
Error Boundary is created via componentDidCatch(error, errorInfo) or static getDerivedStateFromError(error). It does not catch errors in asynchronous code (setTimeout, requestAnimationFrame), server-side rendering, or native errors (Native Modules). For logging, use crash reporting SDK inside componentDidCatch. Error Boundary is a simple but effective error handler for the UI layer.
Fatal error is an unhandled exception that causes an application crash. Non-fatal error is an exception that you caught and handled, but it indicates a problem in the code. Non-fatal errors are logged via Crashlytics/Sentry and help find bugs before they become fatal. Both fatal and non-fatal errors require proper error handling in mobile development.
Frequently Asked Questions
try-catch is a language mechanism for exceptions. Result is a wrapper type that forces error handling at compile time. At IT Sectr, we prefer Result for business logic and try-catch for working with external systems. Both approaches are part of general error handling in Kotlin.
Error Boundary is a React component that catches JavaScript errors in the child component tree and displays a fallback UI instead of crashing the entire application. It does not catch errors in asynchronous code or server-side rendering. Error Boundary is an important element of error handling in mobile applications on React Native.
Crashlytics (Firebase) is the best choice to start with: free, simple integration, automatic crash grouping. Sentry is for projects that need detailed error tracing and performance monitoring. The choice of error handling tool depends on budget and monitoring requirements.
Fatal error is an application crash (uncaught exception). Non-fatal error is an exception that you caught and handled, but it indicates a problem in the code. Non-fatal errors are logged separately and help find bugs before they become fatal. Error handling in a mobile application should include monitoring of both types.
guard let is used for early exit from a function when a value is missing — this makes code more linear and readable. if-let is suitable when an optional is needed inside a block and no function exit is required. guard let is preferred for validating input parameters and is part of error handling in iOS.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.