Kotlin coroutines error handling strategy — `runCatching` and `Result` class
Tags: kotlinresult, kotlinerrorhandling, kotlincoroutines, kotlinruncatching
Published: 2021-05-08 16:00:31

---
title: Kotlin coroutines error handling strategy — `runCatching` and `Result` class
published: true
date: 2021-05-02 20:45:33 UTC
tags: kotlinresult,kotlinerrorhandling,kotlincoroutines,kotlinruncatching
canonical_url: https://hossainkhan.medium.com/kotlin-coroutines-error-handling-strategy-runcatching-and-result-class-14e1467ced6
---

### Kotlin coroutines error handling strategy — `runCatching` and `Result` class

I am trying to learn Kotlin coroutines, and was trying to learn more about how to handle errors from suspended functions. One of the [recommended way](https://developer.android.com/kotlin/coroutines) by Google is to create a “Result” class like the following:

```
sealed class Result<out R> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
}
```

This allows us to take advantage of Kotlin’s when like following:

```
when (result) {  
 is Result.Success<LoginResponse> -> // Happy path  
 else -> // Show error in UI  
}
```

However, I have recently [stumbled into](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/run-catching.html) Kotlin’s runCathing {} API that makes use of Result<T> class [available in standard lib](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/) since 1.3

Here I will try to explore how the native API can replace the recommended example in the Android Kotlin [training guide](https://developer.android.com/kotlin/coroutines) for _simple_ use cases.

![](https://cdn-images-1.medium.com/max/1024/1*km6L-1H-5oTFFKaU3LwwgA.png)<figcaption>Here is a basic idea of how `runCatching {}` can be used from Android ViewModel.</figcaption>

Based on Kotlin standard lib [doc](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/run-catching.html), you can use runCatching { } in 2 different ways. I will focus on one of them, since the concept for other one is similar.

To handle a function that may throw an exception in coroutines or regular function use this:

```
val statusResult: Result<String> = runCatching {
    // function that may throw exception that needs to be handled
    repository.userStatusNetworkRequest(username)
}.onSuccess { status: String -> 
  println("User status is: $status")
}.onFailure { error: Throwable ->  
  println("Go network error: ${error.message}")
}

// Assuming following supposed* long running network API
suspend fun userStatusNetworkRequest(username: String) = "ACTIVE"
```

Notice the ‘[Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/)’ returned from the runCatching this is where the power comes in to write semantic code to handle errors.

The onSuccess and onFailrue callback is part of Result<T> class that allows you to easily handle both cases.

#### How to handle Exceptions

In addition to nice callbacks, the Result<T> class provides multiple ways to recover from the error and provide a default value or fallback options.

1. **Using `getOrDefault()` and `getOrNull()` API**

```
val status: String = statusResult.getOrDefault("STATUS_UNKNOWN")

// Or if nullable data is acceptable use:
val status: String? = statusResult.getOrNull()
```

Since the onSuccess and onFailure returns Result<T> you can chain most of these API calls like following

```
val status: String = runCatching { 
  repository.userStatusNetworkRequest("username")
}
.onSuccess {}
.onFailure {}
.getOrDefault("STATUS_UNKNOWN")
```

**2. Using `recover { }` API**

The recover API allows you to handle the error and recover from there with a fallback value of the same data type. See the following example.

```
val status: Result<String> = runCatching { 
  repository.userStatusNetworkRequest("username")
}
.onSuccess {}
.onFailure {}
.recover { error: Throwable -> "STATUS_UNKNOWN" }  
  
println(status.isSuccess) // Prints "true" when error is received
```

**3. Using `fold {}` API to map data**

The fold extension function allows you to map the error to a different data type you wish. In this example, I kept the user status as String.

```
val status: String = runCatching {
  repository.userStatusNetworkRequest("username")
} 
.onSuccess {} 
.onFailure {} 
.fold(
    onSuccess = { status: String -> status },
    onFailure = { error: Throwable -> "STATUS_UNKNOWN" } 
)
```

Aside from these, there are some additional useful functions and extension functions for Result<T> , take a look at [official documentation](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/) for more APIs.

I hope this was useful or a new discovery for you as it was for me 😊