Kotlin Coroutine Context Element Ordering Causing Unexpected Behavior.

haomin
2 min readApr 29, 2022

I was experimenting with Kotlin coroutine, and noticed some interesting behavior:

Incorrect behavior

Here I am creating a supervisor scope so that the cancellation of the first job should not affect the parent scope and the second job.

The expected behavior is:

  1. CoroutineExceptionHandler is installed for handling uncaught error
  2. Scope is created as a SupervisorScope
  3. With the SupervisorScope, Job 1 and Job 2 are launched
  4. Job 1 instantly throw error, while Job 2 is waiting for it to join
  5. Job 1’s cancellation should not cancel Job 2
  6. Job 1 cancels with exception handled by CorutineExceptionHandler
  7. Job 2 execute normally, program complete normally

However, upon execute the code output is showing:

Incorrect behavior output

Code seems correct, but why the result is not as expected?

Cause of the issue; ordering of adding context elements:

After playing around it a bit with code I noticed that when creating the supervisor scope I was adding coroutine context elements in this order:

val scope = CoroutineScope(ceh + supervisor + coroutineContext)

I added elements in following order:

  1. custom CoroutineExceptionHandler
  2. supervisor job
  3. current coroutineContext from the runBlocking {} scope

And this is causing the unexpected behavior. Turns out the order of which using the + operator to add elements matters!

val scope = CoroutineScope(coroutineContext + ceh + supervisor)

After putting coroutineContext as first element when creating scope, the issue was resolved.

Correct behavior
Expected output

--

--