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.