Skip to main content
Kotlin Basics
CHAPTER 20 Beginner

Exception Handling

Updated: May 18, 2026
5 min read

# CHAPTER 20

Exception Handling

1. Chapter Introduction

Kotlin's compiler is incredibly smart. It prevents Null Pointer Exceptions and Type Mismatches before you even run the code. However, the compiler cannot predict the physical world. What if the user unplugs their internet router while your app is downloading data? What if they type "Hello" into a calculator? These unpredictable events cause Exceptions (Runtime Errors) that will crash your app. In this chapter, we learn how to "catch" these crashes and handle them gracefully.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand what an Exception is.
  • Use try, catch, and finally blocks.
  • Use try as an Expression to assign default values.
  • Throw custom exceptions using the throw keyword.
  • Build a Mini Project: Safe Calculator.

3. The try-catch Block

If you suspect a line of code might crash, you wrap it in a try block. If it crashes, the app stops executing the try block immediately and jumps to the catch block instead of crashing the whole program.
kotlin
123456789101112131415
fun main() {
    val input = "ABC"

    try {
        // This will crash! "ABC" is not a number.
        val number = input.toInt() 
        println("The number is $number") // This line is skipped!
    } catch (e: NumberFormatException) {
        // The crash is caught here!
        println("Error: The input was not a valid number.")
        println("System Message: ${e.message}")
    }
    
    println("Program continues running safely...")
}

4. The finally Block

The finally block is optional. It contains code that will ALWAYS execute, regardless of whether the try block succeeded or crashed. It is primarily used to close files or close database connections.
kotlin
123456789
fun main() {
    try {
        val result = 10 / 0 // ArithmeticException (Divide by zero)
    } catch (e: ArithmeticException) {
        println("Math Error!")
    } finally {
        println("This will print no matter what happens.")
    }
}

5. try as an Expression (Kotlin Superpower)

Just like if and when, try is an Expression in Kotlin. This means you can assign the result of a try-catch block directly to a variable!
kotlin
12345678910111213
fun main() {
    val userInput = "Five"

    // If successful, 'number' equals the Int.
    // If it crashes, 'number' equals 0.
    val number: Int = try {
        userInput.toInt()
    } catch (e: Exception) {
        0 
    }

    println("Saved number: $number")
}

*(Note: For this specific scenario, Kotlin provides toIntOrNull(), but try as an expression is useful for complex network or database operations!)*

6. Throwing Exceptions

Sometimes, you want to trigger a crash yourself to stop invalid data from entering your system. You use the throw keyword.
kotlin
123456789101112131415
fun setAge(age: Int) {
    if (age < 0) {
        // Trigger a custom crash!
        throw IllegalArgumentException("Age cannot be negative! Received: $age")
    }
    println("Age set to $age")
}

fun main() {
    try {
        setAge(-5)
    } catch (e: IllegalArgumentException) {
        println("Caught an error: ${e.message}")
    }
}

7. Checked Exceptions vs Unchecked Exceptions

In Java, if a function might throw an Exception (like reading a file), Java *forces* the developer to wrap it in a try-catch block (Checked Exceptions). Kotlin DOES NOT have Checked Exceptions. Kotlin never forces you to use try-catch. The designers of Kotlin found that forcing developers to catch exceptions led to bloated code with empty catch blocks. It is entirely up to you to catch exceptions when you feel it is necessary.

8. Mini Project: Safe Calculator

Let's build a division calculator that handles multiple types of user errors safely.
kotlin
1234567891011121314151617181920212223
fun main() {
    print("Enter numerator: ")
    val num1Str = readln()
    
    print("Enter denominator: ")
    val num2Str = readln()

    try {
        val num1 = num1Str.toInt()
        val num2 = num2Str.toInt()
        
        val result = num1 / num2
        println("Result: $result")
        
    } catch (e: NumberFormatException) {
        println("Error: Please enter numbers only, not letters.")
    } catch (e: ArithmeticException) {
        println("Error: You cannot divide by zero.")
    } catch (e: Exception) {
        // Catches any other unknown errors
        println("An unknown error occurred.")
    }
}

9. Common Mistakes

  • Catching global Exception for everything: Writing catch (e: Exception) is a "catch-all". It is bad practice because it hides specific bugs. Catch specific exceptions (like NumberFormatException) first, so you know exactly what failed.
  • Empty Catch Blocks: Catching an error and doing nothing (catch(e: Exception) { }). If the app fails, you will have no idea why because the error was silently swallowed. Always log or print the error.

10. Best Practices

  • Use standard library safety features: Before writing a massive try-catch block, check if Kotlin has a safe alternative (like toIntOrNull() or ?.). Only use try-catch for operations involving external systems (File I/O, Network, Databases).

11. Exercises

  1. 1. Write a program that defines an array: val arr = arrayOf(1, 2, 3).
  1. 2. Wrap println(arr[5]) in a try-catch block.
  1. 3. Catch the ArrayIndexOutOfBoundsException and print "Index invalid!".

12. MCQs with Answers

Question 1

What is an Exception in programming?

Question 2

Which block contains the code that might crash?

Question 3

Which block catches the error and executes recovery logic?

Question 4

What is the purpose of the finally block?

Q5. Can try-catch be used as an Expression in Kotlin to assign a value to a variable? a) Yes b) No Answer: a) Yes.
Question 6

What keyword is used to manually trigger an exception?

Q7. Does Kotlin have "Checked Exceptions" (forcing the developer to write try-catch blocks)? a) Yes, like Java b) No, Kotlin does not force you to catch any exceptions Answer: b) No, Kotlin does not force you to catch exceptions.
Question 8

What exception is thrown when you attempt to divide by zero?

Question 9

What exception is thrown when toInt() fails on the string "Apple"?

Question 10

Why is catching the generic Exception class as the first catch block considered bad practice?

13. Interview Questions

  • Q: Why did the creators of Kotlin decide to remove "Checked Exceptions" which were prominent in Java? (Answer: Because forcing developers to catch exceptions often leads to bloated, unreadable code with empty catch blocks, reducing overall code quality).
  • Q: Explain how try can be used as an expression in Kotlin.

14. Summary

No matter how perfect your logic is, interacting with users, networks, or file systems introduces volatility. By utilizing try-catch-finally, your application can intercept crashes, notify the user elegantly, and continue running. Furthermore, Kotlin's ability to use try as an expression keeps error-handling code incredibly concise.

15. Next Chapter Recommendation

We have used listOf and mutableListOf. But what if we need to sort a list, group items, or remove duplicates? In Chapter 21: Collections Framework in Kotlin, we will take a deep dive into advanced list manipulation techniques.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·