Handling errors in a Flow

Flow and StateFlow Mid-level Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Predict the output

What does this print?

fun main() = runBlocking {
    flow {
        emit(1)
        throw IllegalStateException("boom")
    }
        .catch { emit(-1) }
        .onCompletion { println("done") }
        .collect { println(it) }
}
Options
Hint 1 of 1

Which way does catch look: up or down?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A 1, -1, done

Correct. catch handles the upstream error and emits a fallback, then the flow completes.

Why not the others?
  • B 1, then it crashes. catch is upstream of collect, so the error is handled.
  • C -1, done. 1 is emitted before the throw.
  • D 1, done. catch emits -1 before completion.

30-second answer

catch { } handles exceptions from the operators above it, not from below or from the collector. Inside it you can emit a fallback value or rethrow. After catch, the flow completes, so for a long-lived stream put recovery inside an inner flow or use retry/retryWhen before catch to restart the upstream.

Practise saying it · 35 s. No recording, just a timer

Explain error handling in flows.

Say your answer out loud, then check which of these points you covered:

  • catch handles upstream errors only
  • The flow completes after catch
  • retryWhen with delay for backoff
  • onCompletion is like finally

Deep dive

Exceptions thrown in the collect { } block are not caught by catch; move the work into onEach before catch if needed.

retryWhen { cause, attempt -> cause is IOException && attempt < 3 } with a delay gives backoff.

onCompletion { cause -> } runs on success, error or cancellation, like finally.

catch doesn't catch CancellationException from downstream cancellation.

Common mistakes

  • Putting catch at the end and expecting it to catch errors in collect { }.
  • Catching at the top level of a UI state flow so the first error ends it forever.
  • Retrying forever without a delay.

Senior take & follow-ups

Spell out 'upstream only' and the fact that a caught flow completes; that is what bites people.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you show an error and keep listening?

    Show hint

    Catch inside flatMapLatest or map errors to a result type.

  2. What runs in onCompletion?

    Show hint

    Code that must run when the flow ends for any reason.

Suggest a fix if something here is wrong or out of date.