Flow exception handling helps you catch and manage errors when working with streams of data. It keeps your program running smoothly without crashing.
When you want to handle errors while collecting data from a Flow.
When you need to provide fallback values if something goes wrong in the data stream.
When you want to log or show error messages during data processing.
When you want to clean up resources or perform actions after an error occurs in a Flow.
Syntax
Kotlin
flow {
// emit values
}.catch { e ->
// handle exception e
}.collect { value ->
// process value
}
The catch operator catches exceptions inside the Flow before they reach collect.
Use emit inside flow { } to send values.
Examples
This example emits 1, then throws an error. The catch prints the error message.
Kotlin
flow {
emit(1)
throw RuntimeException("Oops")
}.catch { e ->
println("Caught: ${e.message}")
}.collect { value ->
println(value)
}
This example throws an error when value is 2, then catch emits a fallback value -1.
Kotlin
flowOf(1, 2, 3).map {
if (it == 2) throw IllegalStateException("No 2 allowed")
else it
}.catch { e ->
emit(-1) // fallback value
}.collect { println(it) }
Sample Program
This program creates a flow that emits two numbers, then throws an exception. The catch block catches the exception, prints a message, and emits a fallback value 0. The collect prints all received values.
Kotlin
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val numbers = flow {
emit(10)
emit(20)
throw Exception("Error in flow")
emit(30) // won't be reached
}
numbers
.catch { e ->
println("Caught exception: ${e.message}")
emit(0) // fallback value
}
.collect { value ->
println("Received: $value")
}
}
OutputSuccess
Important Notes
The catch operator only catches exceptions from upstream flow operators, not from collect.
Use onCompletion to run code after flow finishes or errors.
Summary
Use catch to handle errors inside a Flow.
You can emit fallback values inside catch.
Exception handling keeps your data stream safe and your app stable.
Practice
(1/5)
1. What is the primary purpose of the catch operator in Kotlin Flow?
easy
A. To start collecting the flow
B. To handle exceptions that occur during the flow emission
C. To transform emitted values into another type
D. To cancel the flow collection
Solution
Step 1: Understand the role of catch in Flow
The catch operator is designed to intercept exceptions that happen during the emission of values in a Flow.
Step 2: Differentiate from other operators
Operators like map transform values, collect starts the flow, and cancel stops it. Only catch handles errors.
Final Answer:
To handle exceptions that occur during the flow emission -> Option B
Quick Check:
Flow error handling = catch [OK]
Hint: Remember: catch is for errors inside Flow [OK]
Common Mistakes:
Confusing catch with map or collect
Thinking catch cancels the flow
Assuming catch transforms values
2. Which of the following is the correct syntax to catch exceptions in a Kotlin Flow?
easy
A. flow.catch { e -> emit(fallbackValue) }
B. flow.try { e -> emit(fallbackValue) }
C. flow.handle { e -> emit(fallbackValue) }
D. flow.error { e -> emit(fallbackValue) }
Solution
Step 1: Recall the correct operator name
The operator to handle exceptions in Kotlin Flow is catch, not try, handle, or error.
Step 2: Verify the lambda syntax
The lambda receives the exception e and can emit fallback values inside it, matching the syntax flow.catch { e -> emit(fallbackValue) }.
Final Answer:
flow.catch { e -> emit(fallbackValue) } -> Option A
A. Missing emit inside catch to provide fallback value
B. catch block should be after collect
C. collect should be inside catch block
D. No error, code is correct
Solution
Step 1: Review catch usage
The catch block prints the exception but does not emit any fallback value, so the flow ends after the exception.
Step 2: Understand flow continuation
Without emitting a fallback value inside catch, the collector won't receive any value after the error, which might not be intended.
Final Answer:
Missing emit inside catch to provide fallback value -> Option A
Quick Check:
catch without emit = no fallback value [OK]
Hint: Emit fallback inside catch to continue flow after error [OK]
Common Mistakes:
Placing catch after collect
Trying to collect inside catch
Not emitting fallback value in catch
5. You want to create a Kotlin Flow that emits numbers 1 to 3, but if an exception occurs, it should emit -1 and then complete. Which code snippet correctly implements this behavior?
hard
A. flow {
for (i in 1..3) emit(i)
}.catch { emit(-1) }
B. flow {
for (i in 1..3) {
if (i == 4) throw Exception()
emit(i)
}
}.catch { emit(-1) }
C. flow {
for (i in 1..3) {
if (i == 2) throw Exception()
emit(i)
}
}.catch { emit(-1) }
D. flow {
for (i in 1..3) emit(i)
}.catch { throw Exception() }
Solution
Step 1: Identify where exception occurs
flow {
for (i in 1..3) {
if (i == 2) throw Exception()
emit(i)
}
}.catch { emit(-1) } throws an exception at i == 2, triggering the catch block to emit -1 as fallback.
Step 2: Confirm fallback emission and completion
The catch block emits -1, then the flow completes. Codes without throwing an exception during the emission loop do not trigger catch. Code that rethrows the exception in catch does not emit fallback.
Final Answer:
flow {
for (i in 1..3) {
if (i == 2) throw Exception()
emit(i)
}
}.catch { emit(-1) } -> Option C
Quick Check:
Throw inside flow + catch emit fallback = flow {
for (i in 1..3) {
if (i == 2) throw Exception()
emit(i)
}
}.catch { emit(-1) } [OK]