thecodex.expert · The Codex Family of Knowledge
Kotlin

Exception Handling

Kotlin deliberately has NO checked exceptions at all — JetBrains considered Java’s throws-declaration requirement a failed experiment that led to swallowed exceptions and boilerplate more often than genuine safety.

Kotlin 2.1 No checked exceptions, by design Last verified:
Canonical Definition

throw raises an exception; try/catch/finally handles it, functioning almost identically to Java's syntax on the surface. The genuinely notable difference is that Kotlin has no checked exceptions whatsoever — no function is ever required to declare throws, and no caller is ever forced to catch or re-declare an exception, a deliberate rejection of Java's design that JetBrains has explained as leading to more boilerplate and swallowed exceptions in practice than genuine safety. Like if and when, try can be used as an expression, directly producing a value from whichever branch actually ran.

Basic try/catch/finally

finally always runs, whether or not an exception occurred — the standard place for cleanup that must happen regardless of success or failure.

Kotlinbasic_exceptions.kt
fun divide(a: Int, b: Int): Int {
    return try {
        a / b
    } catch (e: ArithmeticException) {
        println("Error: ${e.message}")
        0
    } finally {
        println("Division attempted")
    }
}

println(divide(10, 0))   // "Division attempted" then 0

No checked exceptions: a deliberate design choice

readFile compiles fine with zero throws declaration and zero forced try/catch at the call site — Kotlin trusts the programmer to handle exceptions where it genuinely makes sense, rather than mechanically enforcing it everywhere.

Kotlinno_checked_exceptions.kt
import java.io.File

fun readFile(path: String): String {
    return File(path).readText()   // this CAN throw IOException — but no 'throws' needed anywhere
}

val content = readFile("data.txt")   // no forced try/catch here either — entirely the caller's choice

try as an expression

Because try produces a value directly, there's no need for a separate mutable variable declared before the try block and reassigned inside it — the result flows out naturally, the same pattern if and when use.

Kotlintry_expression.kt
val number: Int = try {
    "42".toInt()
} catch (e: NumberFormatException) {
    -1   // fallback value if parsing fails
}

println(number)   // 42

Sources

1
JetBrains. Kotlin Documentation, "Exceptions," kotlinlang.org/docs/exceptions.html.