CoroutineExceptionHandler: manipulador global de exceções não capturadas
Instale um CoroutineExceptionHandler para registrar ou recuperar-se de exceções não tratadas.
CoroutineExceptionHandler: manipulador global de exceções não capturadas é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
O Que é CoroutineExceptionHandler
CoroutineExceptionHandler é um elemento de contexto que trata exceções não capturadas de corrotinas que não têm um manipulador de captura. Ele atua como último recurso.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { context, exception ->
println("Caught unhandled: ${exception.message}")
}
fun main() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default + handler)
scope.launch { throw RuntimeException("oops") }
delay(100)
}Somente para Corrotinas Raiz
CoroutineExceptionHandler captura exceções somente de corrotinas raiz (iniciadas diretamente em um escopo). As corrotinas filhas propagam as exceções para o pai, não para o manipulador.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Root coroutine — handler fires:
CoroutineScope(handler).launch {
throw RuntimeException("root error")
}
delay(100)
// NOT handler (child of coroutineScope):
// launch { launch { throw RuntimeException() } }
}A Exceção Não é Suprimida
O manipulador é chamado depois que a exceção já cancelou a corrotina. Ele serve para registro, relatórios de falhas ou limpeza — não para retomar a execução.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e ->
println("[CrashReport] ${e::class.simpleName}: ${e.message}")
// send to Crashlytics, Sentry, etc.
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).apply {
launch { throw IllegalStateException("state error") }
launch { delay(100); println("still alive") }
delay(200)
cancel()
}
}Manipulador + SupervisorJob
A combinação de SupervisorJob + CoroutineExceptionHandler é o padrão para escopos de longa duração: os filhos falham de forma independente e as falhas não tratadas são registradas.
import kotlinx.coroutines.*
class AppScope {
private val handler = CoroutineExceptionHandler { _, e ->
println("Uncaught: ${e.message}")
}
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
}
fun main() = runBlocking {
val app = AppScope()
app.scope.launch { throw RuntimeException("task failed") }
app.scope.launch { delay(100); println("other task ok") }
delay(200)
app.scope.cancel()
}Manipulador com Execução Assíncrona
Para async, as exceções são armazenadas em Deferred e lançadas em await(). O manipulador NÃO é acionado para async, a menos que o deferred não seja aguardado.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob() + handler)
val deferred = scope.async { throw RuntimeException("async error") }
try {
deferred.await() // exception thrown here
} catch (e: RuntimeException) {
println("Caught from await: ${e.message}")
}
delay(50)
scope.cancel()
}Comparação com UncaughtExceptionHandler de Thread
Ao contrário do UncaughtExceptionHandler do Java, o manipulador do Kotlin faz parte do contexto da corrotina e só se aplica às corrotinas dentro desse escopo.
import kotlinx.coroutines.*
// Java style (applies to threads):
Thread.setDefaultUncaughtExceptionHandler { t, e ->
println("Thread ${t.name} threw: ${e.message}")
}
// Kotlin coroutine style (applies to coroutines in scope):
val handler = CoroutineExceptionHandler { _, e ->
println("Coroutine threw: ${e.message}")
}
fun main() = runBlocking { println("Handlers target different concurrency models") }Padrão de Registro com MDC
Em aplicações de servidor, o manipulador pode capturar informações do contexto da corrotina (como IDs de requisição) para registro estruturado antes de encaminhá-las à estrutura de registro.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { ctx, e ->
val jobName = ctx[CoroutineName]?.name ?: "unknown"
println("[${jobName}] ERROR: ${e.message}")
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).launch(CoroutineName("DataLoader")) {
throw RuntimeException("fetch failed")
}
delay(100)
}Integração com Relatórios de Falhas
Use o manipulador para encaminhar exceções não capturadas a serviços de relatórios de falhas, como Firebase Crashlytics ou Sentry.
import kotlinx.coroutines.*
object CrashReporter {
fun record(e: Throwable) = println("[Crashlytics] ${e.message}")
}
val handler = CoroutineExceptionHandler { _, e ->
if (e !is CancellationException) CrashReporter.record(e)
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
fun main() = runBlocking {
appScope.launch { throw RuntimeException("unhandled in production") }
delay(100)
appScope.cancel()
}Herança do Manipulador
O manipulador do contexto pai NÃO é herdado automaticamente pelas corrotinas filhas. Ele precisa estar no contexto da corrotina raiz para ser acionado.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Handler only fires at root level:
CoroutineScope(SupervisorJob() + handler).launch {
// Child of root — exception propagates to root handler:
launch { throw RuntimeException("nested") }
}
delay(100)
}Resumo das Boas Práticas
Instale sempre um CoroutineExceptionHandler nos escopos do nível da aplicação ou do recurso. Registre toda exceção que não seja de cancelamento. Nunca dependa dele para controlar o fluxo — ele serve apenas à observabilidade.
import kotlinx.coroutines.*
val globalHandler = CoroutineExceptionHandler { ctx, e ->
if (e !is CancellationException) {
println("[ERROR] ${ctx[CoroutineName]?.name}: ${e.message}")
}
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + globalHandler)
fun main() = runBlocking {
appScope.launch(CoroutineName("Auth")) { throw RuntimeException("token expired") }
delay(100); appScope.cancel()
}Verificação Rápida
Para qual tipo de corrotina o CoroutineExceptionHandler NÃO é acionado automaticamente?
Recapitulação
CoroutineExceptionHandler é um observador de último recurso para exceções não capturadas em corrotinas raiz. Combine-o com SupervisorJob para escopos de longa duração. Use-o para registro e relatórios de falhas — nunca para controlar o fluxo.
Perguntas Frequentes
A aula “CoroutineExceptionHandler: manipulador global de exceções não capturadas” é grátis?
Sim — o texto completo de “CoroutineExceptionHandler: manipulador global de exceções não capturadas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “CoroutineExceptionHandler: manipulador global de exceções não capturadas”?
Instale um CoroutineExceptionHandler para registrar ou recuperar-se de exceções não tratadas. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “CoroutineExceptionHandler: manipulador global de exceções não capturadas”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- SupervisorJob vs Job: isolamento de falhas
- CoroutineExceptionHandler: manipulador global de exceções não capturadas
- Propagação de exceções em async/await
- Projetando arquiteturas resilientes de corrotinas