← Back to Kotlin Course | Chapter 13: Error Handling & Testing | Lesson 1 of 6

try, catch, finally

try, catch, and finally let your program attempt something risky, recover if it goes wrong, and still clean up afterward no matter what happened.

Catching an Exception

Wrapping risky code in try { } followed by catch (e: ExceptionType) { } lets the program recover gracefully instead of crashing when that specific kind of exception occurs.

Example: Catching an Exception

markup
fun main() {
    try {
        val result = 10 / 0
        println(result)
    } catch (e: ArithmeticException) {
        println("Caught an error: ${e.message}")
    }
}

Using finally for Cleanup

A finally { } block always executes after the try/catch, regardless of whether an exception was thrown or caught, making it the right place for cleanup code that must always run.

Example: Using finally for Cleanup

markup
fun main() {
    try {
        println("Attempting risky operation")
        throw RuntimeException("Something failed")
    } catch (e: RuntimeException) {
        println("Handled: ${e.message}")
    } finally {
        println("Cleanup always runs")
    }
}

Multiple catch Blocks

Several catch blocks can be chained to handle different exception types differently, and Kotlin checks them in the order they are written, using the first matching type.

Example: Multiple catch Blocks

markup
fun main() {
    val values = listOf("10", "abc", "5")
    for (value in values) {
        try {
            println("Parsed: ${value.toInt()}")
        } catch (e: NumberFormatException) {
            println("Not a number: $value")
        }
    }
}

try as an Expression

Because try can be used as an expression, the value from whichever branch executes -- try or catch -- can be assigned directly to a variable.

Example: try as an Expression

markup
fun parseOrDefault(text: String): Int {
    return try {
        text.toInt()
    } catch (e: NumberFormatException) {
        -1
    }
}

fun main() {
    println(parseOrDefault("42"))
    println(parseOrDefault("oops"))
}
Common Mistakes
  1. Catching a very broad type like Exception everywhere, hiding bugs that should have been fixed rather than silently swallowed.
  2. Forgetting that finally always runs, even if the try or catch block returns early, which is exactly the point of using it for cleanup.
  3. Not realizing try can be used as an expression, producing a value from whichever branch actually ran.
Chapter Summary
  • try { } wraps code that might throw an exception; catch (e: Type) { } handles a specific exception type if one occurs.
  • finally { } always runs after the try/catch, whether or not an exception was thrown, making it ideal for cleanup.
  • Multiple catch blocks can handle different exception types differently, checked in order from top to bottom.
  • try can be used as an expression, with the resulting value coming from whichever branch (try or catch) actually executed.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.