coroutineScope vs supervisorScope

coroutineScope

coroutineScope { } creates a child scope inside a suspend function. It waits for all children, and if any child fails, all the others are cancelled and the exception is thrown to the caller.

Example

Payment fails, so the "send invoice" child is cancelled too.

import kotlinx.coroutines.*

suspend fun placeOrder(): Unit = coroutineScope {
    launch {
        try {
            delay(500)
            println("Invoice sent")
        } catch (e: CancellationException) {
            println("Invoice cancelled")
            throw e
        }
    }
    launch {
        delay(100)
        throw IllegalStateException("Payment declined")
    }
}

fun main() = runBlocking {
    try {
        placeOrder()
    } catch (e: IllegalStateException) {
        println("Order failed: ${e.message}")
    }
}

Output

Invoice cancelled
Order failed: Payment declined

supervisorScope

supervisorScope { } is the same, except a failing child does not cancel its siblings. Each child must handle its own error (try/catch or a CoroutineExceptionHandler).

Example

One widget fails, the other still loads.

import kotlinx.coroutines.*

fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { _, e -> println("Handled: ${e.message}") }
    supervisorScope {
        launch(handler) {
            delay(100)
            throw RuntimeException("Weather widget failed")
        }
        launch {
            delay(300)
            println("News widget loaded")
        }
    }
    println("Screen ready")
}

Output

Handled: Weather widget failed
News widget loaded
Screen ready

Which One?

coroutineScopesupervisorScope
Child failscancels siblings, rethrowssiblings keep running
Use whenall results are needed (all or nothing)tasks are independent
Examplecheckout: payment + stock reservationdashboard widgets, uploading several photos

Exercise: Upload three photos concurrently inside supervisorScope. Photo 2 throws an exception. Make sure photos 1 and 3 still print "uploaded" and the failure is printed by a handler.

Show answer
import kotlinx.coroutines.*

fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { _, e -> println("Failed: ${e.message}") }
    supervisorScope {
        for (i in 1..3) {
            launch(handler) {
                delay(i * 100L)
                if (i == 2) throw RuntimeException("photo 2 too large")
                println("Photo $i uploaded")
            }
        }
    }
}