Result & runCatching
Result<T> is a built-in type that holds either a success value or a captured exception, letting you treat failure as a value you handle rather than an exception that unwinds the stack.
Learn Result & runCatching in our free Kotlin course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Kotlin course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll capture outcomes with runCatching , extract values with getOrNull / getOrElse , and transform with map / fold .
What You'll Learn in This Lesson
1️⃣ runCatching and Result Basics
runCatching {' '} runs the block and returns a Result<T> : a success holding the value, or a failure holding the thrown exception. Check it with isSuccess / isFailure , and read the value with getOrNull() .
2️⃣ Extracting the Value Safely
There are three common extractors. getOrNull() gives the value or null ; getOrDefault(x) gives the value or a constant; getOrElse {' '} gives the value or computes a fallback from the captured exception.
3️⃣ Transforming with map and fold
map transforms the success value and passes failures through untouched, perfect for a happy-path pipeline. fold collapses both branches into one value. onSuccess / onFailure run side effects and return the same Result for chaining.
Your turn. Fill in the ___ blanks, then run and compare.
Use runCatching and fold to report a division that might divide by zero.
📋 Quick Reference — Result API
Practice quiz
What does a Result<T> hold?
- Always both a value and an exception
- Either a success value or a captured exception, never both
- Only a success value
- A list of results
Answer: Either a success value or a captured exception, never both. Result<T> models exactly one of two outcomes: success value or captured failure.
What does runCatching { } return?
- The raw value or it throws
- A Boolean for success
- A Result wrapping success or failure
- Always null on error
Answer: A Result wrapping success or failure. runCatching runs the block and wraps the outcome in a Result.
If the block in runCatching throws, what do you get?
- The exception propagates immediately
- Result.failure(exception)
- Result.success(null)
- A compile error
Answer: Result.failure(exception). runCatching catches the throw and returns Result.failure(exception).
What does getOrNull() return on a failed Result?
- The exception
- An empty string
- Zero
- null
Answer: null. getOrNull() returns the value on success or null on failure.
What does getOrDefault(-1) return when the Result is a failure?
- -1
- null
- The exception
- It throws
Answer: -1. getOrDefault returns the supplied constant fallback on failure.
What does getOrElse { } give you access to in its lambda?
- The success value
- The captured exception, to compute a fallback
- Nothing, it takes no parameter
- The original Result
Answer: The captured exception, to compute a fallback. getOrElse receives the captured exception so the fallback can depend on the error.
What does map do to a failed Result?
- Throws the exception
- Converts it to success
- Leaves the failure untouched and passes it through
- Returns null
Answer: Leaves the failure untouched and passes it through. map transforms only the success value; failures pass through unchanged.
What does fold(onSuccess, onFailure) do?
- Combines two Results
- Collapses the Result into one value by handling both branches
- Only handles the success branch
- Throws on failure
Answer: Collapses the Result into one value by handling both branches. fold produces a single value by handling success and failure in one call.
Which should you use for a transform that might itself throw?
- map
- fold
- getOrNull
- mapCatching
Answer: mapCatching. mapCatching catches exceptions thrown inside the transform; plain map does not.
When is Result the right tool instead of throwing?
- For all exceptions, always
- For expected, recoverable failures the caller should handle
- Only for programmer errors
- Never; always throw
Answer: For expected, recoverable failures the caller should handle. Use Result for expected failures; keep throwing for true bugs that should crash loudly.