Sling Academy
Home/Kotlin/Kotlin: Non-Exhaustive `when` Branch Detected

Kotlin: Non-Exhaustive `when` Branch Detected

Last updated: December 01, 2024

Kotlin is a modern programming language known for its concise syntax and safety features, being particularly popular among Android developers. One pattern frequently encountered when working with Kotlin is writing conditional logic using the when expression. This construct is somewhat similar to the switch statement found in other programming languages but offers Kotlin's twist of being more powerful and expressive.

However, when using the when expression, developers might encounter a compiler warning stating that a "non-exhaustive when branch detected". This is a very important warning to understand and address, as it helps avoid possible runtime crashes. Let’s dive deep into what this warning means, why it arises, and how you can resolve it.

Understanding the when Expression

Firstly, let's explore how the when expression functions in Kotlin. Here is a basic syntax for a when expression:


val color = "blue"
when(color) {
    "red" -> println("Color is red")
    "green" -> println("Color is green")
    "blue" -> println("Color is blue")
    else -> println("Color not recognized")
}

The when statement above checks the value of color against a series of strings. If the value matches any of the conditions, the corresponding block of code is executed. Notice the use of else, which acts similarly to a default case in other languages’ switch-case structures.

The "Non-Exhaustive When Branch Detected" Warning

The warning "non-exhaustive when branch detected" occurs when not all possible cases are covered, and the type being checked is known to have a limited number of instances, such as with an enum class or a defined sealed class hierarchy. The Kotlin compiler emphasizes ensuring all potential cases that may arise at runtime are considered.

Say you have an enum in Kotlin:


enum class Direction {
    NORTH, SOUTH, EAST, WEST
}

Using this enum in a when expression like so:


fun getDirectionMessage(direction: Direction): String {
    return when(direction) {
        Direction.NORTH -> "You are heading north"
        Direction.SOUTH -> "You are heading south"
        //Notice: Missing cases for EAST and WEST
    }
}

Because it is not exhaustive (i.e., not all enum values are covered in the when expression) and the specific Direction enum values can lead to an unmanaged state, thus causing the compilation warning.

Resolving the Warning

Handling this is fairly straightforward—ensure all relevant cases are covered explicitly, including using else as a fallback for unexpected or undefined values.

To handle all cases properly, you would cover all enum values:


fun getDirectionMessage(direction: Direction): String {
    return when(direction) {
        Direction.NORTH -> "You are heading north"
        Direction.SOUTH -> "You are heading south"
        Direction.EAST -> "You are heading east"
        Direction.WEST -> "You are heading west"
    }
}

Or alternatively, you can make use of the else branch to manage unexpected input:


fun getDirectionMessage(direction: Direction): String {
    return when(direction) {
        Direction.NORTH -> "You are heading north"
        Direction.SOUTH -> "You are heading south"
        else -> "You are heading in a different direction"
    }
}

Caution: Using else can sometimes suppress our ability to catch new additions or changes, like a new direction added to the enum, unless cautious revisions are made.

Sealed Classes

The same principle applies to Kotlin's sealed classes, which enforce the developer to handle potential subclasses explicitly.

Example:


sealed class HttpResponse
class Success : HttpResponse()
class Error(val errorCode: Int) : HttpResponse()

fun handleResponse(response: HttpResponse) = when(response) {
    is Success -> println("Request successful")
    is Error -> println("Received error code: ")
    // Suppose another subclass, say `Redirect`, is added later
}

Again, once we don't handle each subclass, the warning will emerge, which enforces us to handle all known types distinctly to prevent unexpected behavior.

Conclusion

The "non-exhaustive when branch detected" warning is a helpful feature of Kotlin aiming to encourage programmers to explicitly manage every defined scenario, thus lessening the prospects of run-time errors. Through enum declarations or sealed classes, always strive to include all possible outcomes in your when expressions to fully utilize Kotlin's capabilities and avoid these warnings.

Next Article: Kotlin: Syntax Error: Missing `}` in Block

Previous Article: Kotlin: Cannot Override Final Property Warning

Series: Common Errors in Kotlin and How to Fix Them

Kotlin

You May Also Like

  • How to Use Modulo for Cyclic Arithmetic in Kotlin
  • Kotlin: Infinite Loop Detected in Code
  • Fixing Kotlin Error: Index Out of Bounds in List Access
  • Setting Up JDBC in a Kotlin Application
  • Creating a File Explorer App with Kotlin
  • How to Work with APIs in Kotlin
  • What is the `when` Expression in Kotlin?
  • Writing a Script to Rename Multiple Files Programmatically in Kotlin
  • Using Safe Calls (`?.`) to Avoid NullPointerExceptions in Kotlin
  • Chaining Safe Calls for Complex Operations in Kotlin
  • Using the Elvis Operator for Default Values in Kotlin
  • Combining Safe Calls and the Elvis Operator in Kotlin
  • When to Avoid the Null Assertion Operator (`!!`) in Kotlin
  • How to Check for Null Values with `if` Statements in Kotlin
  • Using `let` with Nullable Variables for Scoped Operations in Kotlin
  • Kotlin: How to Handle Nulls in Function Parameters
  • Returning Nullable Values from Functions in Kotlin
  • Safely Accessing Properties of Nullable Objects in Kotlin
  • How to Use `is` for Nullable Type Checking in Kotlin