Retry recovers from selected Flow failures by deciding whether to collect the upstream operation again, rather than terminating immediately. The retry predicate inspects the exception, and a true result permits another attempt up to the configured maximum. section 18.4.2
Listing 18.10 Retrying the collection of an unreliable flow
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.*
import kotlin.random.Random
class CommunicationException : Exception("Communication failed!")
val unreliableFlow = flow {
println("Starting the flow!")
repeat(10) { number ->
if (Random.nextDouble() < 0.1) throw CommunicationException()
emit(number)
}
}
fun main() = runBlocking {
unreliableFlow
.retry(5) { cause ->
println("\nHandled: $cause")
cause is CommunicationException
}
.collect { number ->
print("$number ")
}
}
A Kotlin example retries an unreliable ten-element flow up to five times, continuing only for CommunicationException. Each retry starts collection from the beginning. section 18.4.2
Use retry with these operational constraints:
- Restarting collection reruns every upstream operator, including side effects. section 18.4.2
- Make repeated side effects idempotent or handle their repetition explicitly. section 18.4.2
- Distinguish retry from catch: catch processes upstream exceptions, while retry gives collection another chance. section 18.6




















