Per default Kotlin only requires when-expressions to be exhaustive if the result is assigned to a variable. However when the result is not assigned to a variable, no exhaustiveness checks are performed.

val foo: Boolean = false

// Error: 'when' expression must be exhaustive, add necessary 'false' branch or 'else' branch instead
val bar = when (foo) {
true -> println("yes")
}

// Compiles without error
val bar = when (foo) {
true -> println("yes")
false -> println("no")
}

// Compiles without error
when (foo) {
true -> println("yes")
}


There is currently an open issue KT-12380 about this and some discussion regarding compiler warnings and exhaustiveness checks. Additionally there is the cashapp/exhaustive library which adds an @Exhaustive annotation and contains some discussions how to resolve or mitigate the issue. If one wants to avoid pulling external dependencies an exhaustiveness check can also easily be added with a tiny utility function.

fun <T> T.exhaustive get() = Unit

val foo: Boolean = false

// Error: 'when' expression must be exhaustive, add necessary 'false' branch or 'else' branch instead
when (foo) {
true -> println("yes")
}.exhaustive

// Compiles without error
when (foo) {
true -> println("yes")
false -> println("no")
}.exhaustive


By defining a dummy extension property (exhaustive) on all types and accessing it on the return value of the when-expression we effectively get the same behavior as when we assigned the result to a variable and thus force the when-expression to be exhaustive.