Where CoroutineExceptionHandler works

Coroutines Senior Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Pick the fix

The handler never logs, and the app crashes. Which change makes it fire?

val handler = CoroutineExceptionHandler { _, e -> log("caught $e") }
scope.launch {
    launch(handler) {
        throw IOException("offline")
    }
}
Options
Hint 1 of 1

Which coroutine is the root here?

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

Show answer

Answer: A Install the handler on the scope (or the outer launch), not the inner one

Correct. Only the root coroutine's handler is used; the inner child passes the exception to its parent.

Why not the others?
  • B Switch the inner launch to async. async never reports to a handler; its exception waits for await.
  • C Add Dispatchers.IO to the inner launch. The dispatcher has nothing to do with exception handling.
  • D Wrap the outer launch in try/catch. launch returns at once; the exception happens later inside the coroutine.

30-second answer

A CoroutineExceptionHandler only handles uncaught exceptions in root coroutines, or in direct children of a supervisor, started with launch. Installed on a nested child, it is ignored, because the child passes the failure up to its parent. It never catches exceptions from async; those surface at await.

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

Explain where CoroutineExceptionHandler works.

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

  • Root or supervised launch only
  • Ignored on nested children
  • Doesn't catch async failures
  • Use try/catch to recover

Deep dive

Think of it as the last stop before a crash, for logging and showing a generic error, not for recovery.

To recover from one call, use try/catch around it inside the coroutine.

Exceptions from async are stored in the Deferred and rethrown by await; wrap the await.

By the time the handler runs, the coroutine is already finished; you can't resume it.

Common mistakes

  • Putting the handler on an inner launch and expecting it to fire.
  • Expecting the handler to catch async failures.
  • Using the handler as normal error handling instead of try/catch.

Senior take & follow-ups

A crisp answer: root or supervised launch only; async goes to await; use try/catch for recovery.

Follow-up questions

Think of your answer first, then open the hint.

  1. Does the handler run on cancellation?

    Show hint

    No, CancellationException is ignored by handlers.

  2. How do you report all uncaught failures in an app scope?

    Show hint

    Install one handler on the application scope's context.

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