Coroutine Exceptions & Error Handling Flashcards

KOTLIN › Coroutines

Why does try { scope.launch { throw ... } } catch { } never catch anything?
launch returns as soon as the coroutine is scheduled, so the try block has already exited by the time the body runs. The exception fails the coroutine Job and propagates up the job hierarchy, which is a different path entirely from the call site.
Where does a CoroutineExceptionHandler have to be installed to work?
On a coroutine that is a **root** of its scope: on the scope context itself, on a top-level launch, or on a direct child of supervisorScope. Installed on a nested child it is ignored, because that child reports its failure to its parent instead of handling it.
Does CoroutineExceptionHandler work for async?
No. An async coroutine stores its exception in the Deferred for retrieval at await(), and the handler is never consulted regardless of where it is installed.
Why is CancellationException exempt from failure propagation?
Because it signals intentional shutdown, not a problem. It never reaches a CoroutineExceptionHandler, never cancels a parent, and never fails siblings. A parent cancelling its children completes normally.
What is wrong with catch (e: Exception) around a suspending call?
It also catches CancellationException, so the coroutine ignores cancel() and keeps running after its scope is gone. Either catch narrowly, or add catch (e: CancellationException) { throw e } before the broad clause.
Two sibling coroutines fail at once. What does the caller receive?
The first failure to reach the parent, with the second attached to it as a **suppressed** exception. There is no composite wrapper, which is why logging only e.message can hide sibling failures.
What happens to the other async calls when one fails inside coroutineScope?
They are cancelled. The failure propagates to the scope, which cancels every sibling, and the original exception is rethrown from the scope. There are no partial results unless you isolate the optional call yourself.
How deep does supervisorScope isolation reach?
One level. Direct children are isolated from each other, but a grandchild reports to its own ordinary parent, so that inner subtree still cancels as a unit. The supervisor only stops the failure spreading to the outer siblings.
What is the hidden danger of runCatching inside a coroutine?
It catches Throwable, including CancellationException, so a cancelled coroutine carries on as if the call merely failed. Use a wrapper that rethrows CancellationException before converting anything else to a failure.
What happens to a root async exception that is never awaited?
It is stored in the Deferred and silently lost. Handlers are ignored for async, and with no parent watching and no await(), nothing ever surfaces it. Only use async when you intend to await.
Is TimeoutCancellationException a failure?
No. It is a CancellationException subclass, so withTimeout cancels only its own block rather than failing the enclosing scope, and catching it requires a specific clause rather than a broad one.
What is the right layering for coroutine error handling?
Repositories convert exceptions into values (Result or a sealed type), ViewModels convert those values into UI state. Failure becomes part of the signature, so callers cannot forget it and the ViewModel needs no try/catch.

Back to Coroutine Exceptions & Error Handling