Careeroza
CoroutineExceptionHandler
Last-resort Handler
A CoroutineExceptionHandler is called for exceptions that nobody caught. It works only on a root coroutine (launched directly in a scope) or a direct child of a supervisor. It is the place to log the crash and show a generic error. It cannot "recover" the coroutine: it is already finished.
Example
import kotlinx.coroutines.*
fun main() = runBlocking {
val handler = CoroutineExceptionHandler { context, e ->
val name = context[CoroutineName]?.name
println("Crash in '$name': ${e::class.simpleName}: ${e.message}")
}
val appScope = CoroutineScope(SupervisorJob() + handler)
val job = appScope.launch(CoroutineName("syncContacts")) {
delay(50)
throw IllegalStateException("contacts permission missing")
}
job.join()
appScope.launch(CoroutineName("syncPhotos")) {
println("Scope still works after a failure")
}.join()
appScope.cancel()
}Output
Crash in 'syncContacts': IllegalStateException: contacts permission missing Scope still works after a failure
Where Handlers Are Ignored
- On a nested child of a normal
Job: the exception goes to the parent first, the child handler is ignored. - On
async: the exception is kept forawait(). - For
CancellationException: it is a normal cancel, not an error.
Tip: On Android, install one handler in your app-level scope that logs to Crashlytics, and still catch expected errors (network, validation) close to where they happen.