100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Rust

Error Handling in Rust (Result)

Learn how Rust models recoverable errors with the Result enum and the ? operator instead of exceptions.

Error HandlingIntermediate9 min readJul 8, 2026
Analogies

Introduction

Rust has no try/catch and no exceptions. Instead, recoverable errors are represented as values using the Result<T, E> enum, which forces the caller to explicitly handle both the success and failure cases at compile time. This makes error paths visible in function signatures rather than hidden as control-flow jumps.

🏏

Cricket analogy: Rust has no umpire-review exception system; instead every risky run attempt returns a Result — Out or NotOut — forcing the batting captain to check the outcome explicitly rather than assume safety.

Syntax

rust
enum Result<T, E> {
    Ok(T),
    Err(E),
}

fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        return Err(String::from("division by zero"));
    }
    Ok(a / b)
}

Explanation

A function that can fail returns Result<T, E>, where T is the success type and E is the error type. Callers use match, if let, or combinators like .map() and .unwrap_or() to handle both variants. The ? operator can be placed after an expression that returns a Result: if the value is Err, the function returns immediately with that Err; if it is Ok, the inner value is unwrapped and execution continues. The ? operator only works inside functions that themselves return a Result (or Option) type.

🏏

Cricket analogy: A run-chase function returning Result<Runs, String> is handled with match or .unwrap_or(0); the ? operator is like a captain who, on a Err(rain_stopped), immediately ends the innings report rather than continuing.

Example

rust
use std::num::ParseIntError;

fn parse_and_double(input: &str) -> Result<i32, ParseIntError> {
    let n: i32 = input.parse()?; // propagate error early
    Ok(n * 2)
}

fn main() {
    match parse_and_double("21") {
        Ok(value) => println!("Doubled: {}", value),
        Err(e) => println!("Failed to parse: {}", e),
    }

    match parse_and_double("abc") {
        Ok(value) => println!("Doubled: {}", value),
        Err(e) => println!("Failed to parse: {}", e),
    }
}

Output

rust
Doubled: 42
Failed to parse: invalid digit found in string

Key Takeaways

  • Result<T, E> = Ok(T) | Err(E) is Rust's mechanism for recoverable errors — there are no exceptions.
  • The ? operator propagates an Err up the call stack and unwraps Ok values, but only inside functions returning Result or Option.
  • .unwrap() and .expect("msg") panic on Err and are best reserved for prototypes, tests, or truly unrecoverable states.
  • Error handling is explicit and checked by the compiler, so failure paths cannot be silently ignored.
  • Combinators like .map(), .map_err(), .and_then(), and .unwrap_or() let you transform Results without manual match blocks.

Practice what you learned

Was this page helpful?

Topics covered

#Rust#RustProgrammingStudyNotes#Programming#ErrorHandlingInRustResult#Error#Handling#Result#Syntax#ErrorHandling#StudyNotes#SkillVeris