Exploring Rich Errors in Kotlin: A Game-Changer from KotlinConf 2025

At KotlinConf 2025, JetBrains unveiled exciting updates for Kotlin, with one of the standout features being rich errors. This upcoming language feature, set to be released in Kotlin 2.4, promises to enhance error handling by making it more type-safe, concise and expressive. Let’s dive into what rich errors are and why they’re generating so much buzz in the Kotlin community.

What Are Rich Errors?

Rich errors introduce a new approach to error handling in Kotlin by leveraging restricted union types. Rich errors allow developers to define functions that return either a success value or specific error types (e.g., User | FetchingError). This eliminates the need for workarounds like sealed classes or null-based error handling, making code more readable and maintainable.

error object FetchingError
error class TransactionError(val errorMessage: String)

fun fetchUser(): User | FetchingError
fun User.charge(amount: Double): TransactionId | TransactionError

Here, the fetchUser function can return either a User object or a FetchingError, and the charge function returns either a TransactionId or a TransactionError. This approach provides clear, type-safe control flow, allowing developers to handle errors elegantly:

val user = fetchUser()
val transaction = user?.charge(amount = 10.0)
when (transaction) {
is TransactionId -> println("Transaction succeeded")
is FetchingError -> println("Fetching failed")
is TransactionError ->
println("Transaction failed: ${transaction.errorMessage}")
}

This improves code clarity by explicitly defining possible outcomes without relying on nulls.

Comparing with Traditional Approaches

To appreciate the elegance of rich errors, let’s compare them with traditional error-handling methods in Kotlin: sealed classes and null-based error handling.

Sealed Classes: Sealed classes are a common way to model success and error states in Kotlin, but they often introduce verbose boilerplate. For example:

sealed class Result {
data class Success(val user: User) : Result()
data class Error(val error: FetchingError) : Result()
}
fun fetchUser(): Result

While sealed classes provide type safety, they require defining a hierarchy of subclasses, wrapping results in Success or Error objects, and handling them with additional verbosity. This can clutter code, especially in complex applications with many error types.

Null-Based Error Handling: Another common approach is using nullable types, such as User?, where null indicates an error. For example:

fun fetchUser(): User?
val user = fetchUser()
if (user == null) {
println("Error: User not found") // Vague error handling
} else {
println("Got user: $user")
}

This method lacks expressiveness, as null doesn’t convey specific error details, forcing developers to rely on documentation or separate error-tracking mechanisms. It also increases the risk of null pointer exceptions if checks are overlooked.

Why Rich Errors Matters

  1. Improved Type Safety: By integrating error types directly into the return type, rich errors ensure that all possible error cases are accounted for at compile time, reducing runtime surprises.
  2. Conciseness: Rich errors eliminate the need for wrapper classes like Result and provide explicit error types instead of null.
  3. Enhanced Readability: The | syntax clearly communicates possible outcomes, and the type system ensures all cases are handled at compile time, reducing boilerplate and improving clarity.

What’s next?

While rich errors are scheduled for Kotlin 2.4, they’re still in the proposal stage, with more details expected as the release approaches. The feature’s introduction at KotlinConf 2025, highlighted in the talk “Rich Errors in Kotlin” by Michail Zarechenskiy, has sparked enthusiasm for its potential to streamline error handling in Kotlin.

Further reading:

https://blog.jetbrains.com/kotlin/2025/05/kotlinconf-2025-language-features-ai-powered-development-and-kotlin-multiplatform/#

https://youtrack.jetbrains.com/issue/KT-68296


Exploring Rich Errors in Kotlin: A Game-Changer from KotlinConf 2025 was originally published in Compendium on Medium, where people are continuing the conversation by highlighting and responding to this story.