Avoid suspend function calls in `runCatching`KT-W1066
suspend
functions should not be called within runCatching
, as doing so will cause all exceptions, including coroutine control flow related ones to be caught.
Coroutines throw exceptions to facilitate structured concurrency and easy job cancellation via CancellationException
s.
For this behavior to work correctly, CancellationException
s must never be:
- caught and swallowed (even if logged)
- caught and propagated to external systems
- caught and shown to the user.
CancellationException
must always be rethrown in the same context.
Using runCatching
increases this risk of mis-handling cancellation. If you catch and don't rethrow all CancellationException
s encountered,
your coroutines will not stop executing even if their parent CoroutineScope
was cancelled. This can very easily lead to unexpected crashes, truant jobs and other extremely hard to diagnose bugs.
Bad Practice
@Throws(IllegalStateException::class)
suspend fun bar(delay: Long) {
check(delay <= 1_000L)
delay(delay)
}
suspend fun foo() {
runCatching {
bar(1_000L)
}
}
Recommended
Move suspend calls outside of runCatching
's lambda, or use an implementation of runCatching
that will rethrow CancellationException
s without handling them.
@Throws(IllegalStateException::class)
suspend fun foo() {
bar(1_000L)
}