
Exception Handling in Kotlin Coroutines: launch vs async
When working with Kotlin coroutines, you have two options for launching a new coroutine and handling exceptions: launch
and async
. Let's explore the differences in exception handling between these two constructs:
launch
:
When using the launch
coroutine builder, exceptions are not propagated to the caller by default. It follows the "fire and forget" principle, where the launched coroutine runs independently without returning any result or propagating exceptions to the handler if specified. Any exceptions thrown within the launch
block will not affect the surrounding code.
Exception handling in launch
:
- By default, uncaught exceptions in a
launch
coroutine are propagated to the parent scope's exception handler. If the parent scope doesn't have an exception handler, the exception will be thrown and may result in application termination if unhandled. - You can also specify a custom exception handler using the
CoroutineExceptionHandler
context element. This allows you to define a specific handler for eachlaunch
coroutine, enabling you to handle and log exceptions or perform any necessary cleanup actions.

async
:
On the other hand, async
coroutine builder returns a Deferred
result. A Deferred
is a lightweight non-blocking future that represents a deferred result of a computation. It allows you to handle exceptions that occur within the coroutine explicitly. By using the await()
function on the Deferred
object, you can retrieve the result while catching any exceptions that may have occurred.
Exception handling in async
:
- Exceptions that occur within an
async
coroutine are not immediately thrown. Instead, they are stored within the resultingDeferred
object. - To retrieve the result of the
async
computation and handle any exceptions, you need to explicitly call theawait()
function on theDeferred
object. This will either return the result value or throw the stored exception if one occurred during the computation.

In summary, the key difference between launch
and async
in terms of exception handling is that exceptions in launch
are immediately propagated, while exceptions in async
are stored within the Deferred
object and need to be explicitly handled when calling await()
. Choose the appropriate coroutine builder based on your use case