suspendRunCatching

inline suspend fun <T> suspendRunCatching(crossinline block: suspend () -> T): Result<T>

Executes a suspending operation and returns the result wrapped in Result, with proper coroutine cancellation handling.

This is the standard error handling utility used across all repository methods in the application. It's similar to Kotlin's runCatching but properly handles coroutine cancellation by re-throwing CancellationException instead of catching it.

Why Use This Instead of runCatching?

The standard runCatching catches ALL exceptions, including CancellationException, which breaks coroutine cancellation. This function preserves cancellation behavior while catching other exceptions.

Usage in Repository Layer

class UserRepositoryImpl @Inject constructor(
private val networkDataSource: NetworkDataSource,
private val localDataSource: LocalDataSource,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
) : UserRepository {

override suspend fun getUser(id: String): Result<User> = suspendRunCatching {
withContext(ioDispatcher) {
networkDataSource.getUser(id)
}
}

override suspend fun syncUsers(): Result<Unit> = suspendRunCatching {
withContext(ioDispatcher) {
val users = networkDataSource.getUsers()
localDataSource.saveUsers(users)
}
}
}

Integration with State Management

This function is designed to work seamlessly with updateStateWith and updateWith:

@HiltViewModel
class UserViewModel @Inject constructor(
private val repository: UserRepository
) : ViewModel() {
fun loadUser(id: String) {
_uiState.updateStateWith {
repository.getUser(id) // Already wrapped in Result via suspendRunCatching
}
}
}

Exception Handling

  • Success: Returns Result.success(value)

  • CancellationException: Re-thrown to preserve coroutine cancellation

  • Other exceptions: Returns Result.failure(exception)

Best Practices

  • Use at the repository boundary (not in ViewModels or UI)

  • Combine with withContext(ioDispatcher) for IO operations

  • Let exceptions propagate from data sources unchanged

  • Don't nest multiple suspendRunCatching calls

Return

Result.success with the value if successful, Result.failure if an exception occurred.

Parameters

T

The type of the result value.

block

The suspending operation to execute.

See also

updateStateWith
updateWith

Throws

if the coroutine is cancelled (not caught).