liveBook · Manning

Supervisor

As explained in Kotlin in Action, 2E

A supervisor is a coroutine failure-isolation mechanism that defines a boundary within which child coroutine failures do not automatically cancel sibling coroutines or the supervising scope.

A supervisor is a coroutine boundary for work that should remain independent after one child fails. Under a regular Job, an uncaught child exception cancels its parent and sibling coroutines; this is useful when concurrent tasks must produce one shared result. A supervisor instead survives child failure, lets siblings continue, and stops that failure from propagating to its parent. section 18.2.1 section 18.2.3

Keep independent work alive with supervisorScope

Wrap independently useful children in supervisorScope. Here, the heartbeat continues after the other launch throws: runBlocking { supervisorScope { launch { while (true) { println("Heartbeat!") delay(500.milliseconds) } } launch { delay(1.seconds) throw UnsupportedOperationException("Ow!") } } } supervisorScope is analogous to coroutineScope, but a failed child neither terminates its siblings nor cancels the enclosing parent. The failed launch can still report its uncaught exception through a CoroutineExceptionHandler. section 18.2.3 section 18.3

Create or choose a supervising boundary when child tasks have separate lifetimes or failure policies:

  • Use supervisorScope to isolate children within an existing coroutine while retaining structured concurrency. section 18.2.3
  • Create a CoroutineScope with SupervisorJob when a component owns longer-running work. section 18.2.3 section 18.3
  • Keep cancellation handling intact: supervisors can still be cancelled and propagate cancellation exceptions normally. section 18.2.3
  • Catch exceptions inside a child when that child itself can recover; this also prevents an exception from crossing the coroutine boundary. section 18.2.2
Figure 18.2 When one or more child coroutines of a supervisor fail, the sibling and parent coroutines all keep on working. The exception is no longer propagated further.
CH18_F02_Isakova

The failure boundary is visible here: a child may fail while its supervisor, parent, and sibling coroutines continue. section 18.2.3

Supervision is not exception recovery. An uncaught exception is isolated from the parent hierarchy, but a launch child can still reach the applicable CoroutineExceptionHandler. With async, the exception is rethrown when await is called, so the awaiting code remains responsible for handling it. Framework scopes may already be supervisors; Ktor’s Application scope is one example, while Android viewModelScope uses a SupervisorJob without necessarily supplying a CoroutineExceptionHandler. section 18.6 section 18.3

How Kotlin in Action, 2E covers it

How deep it goes
Explains SupervisorJob and supervisorScope through a heartbeat example, then connects uncaught launch failures to CoroutineExceptionHandler.
Examples
Uses a repeating heartbeat alongside a delayed UnsupportedOperationException, plus a component scope with custom exception logging.
What it assumes
Assumes familiarity with coroutine parent-child Job hierarchies and introduces supervision as an error-propagation boundary.
What you can do after
Apply it via SupervisorJob or supervisorScope to keep sibling coroutines running after an uncaught child failure.
How it connects
Connects structured concurrency, Job, SupervisorJob, supervisorScope, coroutineScope, launch, async, await, and CoroutineExceptionHandler.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Kotlin in Action, 2E. The section links point to the parts of the book it draws on.