How do you guys usually handle exceptions in corou...
# coroutines
m
How do you guys usually handle exceptions in coroutines while still propagating cancelations? It always feels a little clunky and with too much boiler plate since coroutines are built to use exceptions but kotlin doesnt have checked exceptions so you usually have to do
Copy code
try {
    exceptionalMethod()
catch (e: Exception) {
    if (e is CancellationException) {
       throw e
    }
    // handle other exceptions 
}
Would it be worth writing a some sort of top level function similar to runCatching that does the above? Or are there cleaner solutions?
And since I know I’ll probably get comments suggesting something like
Either
in Arrow instead of throwing exceptions from suspend functions, I’d rather not go through the effort of convincing my team to bring in a new library
k
If you don't rethrow the cancellation, is the stack not unwinding?
m
I was thinking more in the sense of maintaining the propagation of cancellations while also dealing with methods that throw exceptions to indicate an error
So if you dont rethrow the cancellation then the parent coroutine doesn’t get cancelled
👌 1
s
It looks like Kotlin really wants to you catch only the specific exceptions that are not fatal (recoverable in some form) and let all the others ‘crash’ your application, by discouraging a
catch (t: Throwable)
clause….
b
In any language with exceptions, you really should only catch exceptions that you are able to handle. Another option is to provide a catch for cancellations and rethrow from there as well
Copy code
inline fun <R> runCancellable(block: 
() -> R) = runCatching(block).onFailure {
    if (it is CancellationException) {
        throw it
    }
}
1
s
I wish there was a (suspend)
runCatching
variant that already did the rethrowing of a CancellationException …. 🙂
1
m
Yea ideally only catching expected exceptions is the way to go but without checked exceptions like in java that feels a bit error prone
s
Thing is, it should be discouraged to handle `Throwable`s wholesale, but
runCatching
does just that and when used in Coroutines, using
runCatching
may cause serious issues (cancellations not propagated). May be worth reporting this as an issue….
m
@streetsofboston What do you think the solution would be from an api perspective?
s
Provide a
runCatching
variation (with slightly different name) that does not catch a CancallationException and re-throws it instead. And a lint-warning if the code contains a plain runCatching inside a Coroutine (suspendable code), urging the user to use the new one instead (that rethrows a CancellationException)
m
Ah so something similar to what @bdawg.io proposed.
s
Yup, but then as part of the Kotlinx.Coroutines package and having lint-warnings.
👍 1
https://github.com/Kotlin/kotlinx.coroutines/issues/1814 (edited the title to include the word ‘not’)