Coroutine Exceptions & Error Handling
KOTLIN › Coroutines
How failure travels through the job hierarchy, and which tool catches it where.
Coroutine error handling confuses people because an exception in a coroutine is a failure of its Job, not an exception at the call site that started it. Interviewers use this to check whether you understand the job hierarchy: why try/catch around launch never fires, exactly where a CoroutineExceptionHandler is consulted, why async behaves differently, and why CancellationException is exempt from all of it. Strong answers treat the handler as a last-resort crash reporter and put recoverable failures in a Result or a typed catch where the code that can respond will see them.
What this covers
- An exception in a coroutine fails its Job and travels up the job hierarchy; try/catch around the builder never fires
- try/catch works inside the coroutine, around the suspending call, and must be narrow or rethrow CancellationException
- launch reports failure to its parent immediately; async does that too and additionally stores it for await()
- CoroutineExceptionHandler is consulted only for a root coroutine, is ignored for async, and never sees CancellationException
- Under supervisorScope each direct child acts as a root, which is why a handler on a child fires there but not under coroutineScope
- supervisorScope isolates direct children only: a grandchild failure still cancels its own sibling group
- When siblings fail together the first exception is thrown and the rest are attached as suppressed
- runCatching catches Throwable including CancellationException, so wrap suspending calls with a typed helper instead
- Repositories turn exceptions into Result or a sealed type; ViewModels turn those into UI state
Study this topic
- Coroutine Exceptions & Error Handling explained: the guided lesson
- 16 practice quiz questions
- 12 revision flashcards
- Coroutine Exceptions & Error Handling interview questions and answers