Rust Tutorial
Estimated reading: 4 minutes 287 views

🦀 Rust – Error Handling: Handle Failures Safely with Result & Option

Introduction – Why Learn Error Handling in Rust?

Rust’s approach to error handling is explicit, type-safe, and compiler-enforced. Unlike many languages that use exceptions, Rust uses Result and Option enums to model recoverable and non-recoverable errors at compile time, reducing bugs and panics in production code.

In this guide, you’ll learn:

  • The difference between panic!, Option, and Result
  • How to handle errors with match, unwrap, and ?
  • How to propagate errors in functions
  • Code examples with output and line-by-line explanations

panic! – Non-recoverable Error (Crash on Purpose)

Code Example:

fn main() {
    panic!("Something went wrong!");
}

Output:

thread 'main' panicked at 'Something went wrong!', src/main.rs:2:5
note: run with `RUST_BACKTRACE=1` for a backtrace

Use panic! only when continuing execution is unsafe or meaningless.


Option – Value Might Be Absent

Used when a value might not exist, like indexing or searching.

Code Example:

fn main() {
    let nums = vec![1, 2, 3];
    match nums.get(5) {
        Some(n) => println!("Found: {}", n),
        None => println!("No value at index"),
    }
}

Output:

No value at index

Option<T> has two variants: Some(value) or None.


Result<T, E> – Recoverable Errors

Used for file operations, network requests, etc.

Code Example:

use std::fs::File;

fn main() {
    let file = File::open("nonexistent.txt");

    match file {
        Ok(_) => println!("File opened successfully"),
        Err(e) => println!("Failed to open file: {}", e),
    }
}

Output:

Failed to open file: No such file or directory (os error 2)

Propagating Errors with ? Operator

Use ? to return errors automatically if an operation fails.

Code Example:

use std::fs::File;
use std::io::{self, Read};

fn read_file() -> Result<String, io::Error> {
    let mut file = File::open("data.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}

fn main() {
    match read_file() {
        Ok(text) => println!("File content:\n{}", text),
        Err(e) => println!("Error reading file: {}", e),
    }
}

? simplifies error handling by bubbling up errors.


unwrap() and expect() – Panic on Error

Code Example:

fn main() {
    let val: Option<i32> = None;
    // let num = val.unwrap(); //  Panics
    let num = val.expect("Expected a number"); //  Better panic message
}

Avoid unwrap() in production unless you’re certain the value is valid.


Defining Your Own Error Type

For advanced cases, define a custom error type with enum.

use std::fmt;

enum MyError {
    NotFound,
    InvalidInput,
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            MyError::NotFound => write!(f, "Item not found"),
            MyError::InvalidInput => write!(f, "Input is invalid"),
        }
    }
}

Custom errors make your APIs expressive and ergonomic.


Option vs Result vs panic!

MechanismUse CaseReturn TypeSafe?
OptionMissing valueSome(T) / None Yes
ResultRecoverable errorsOk(T) / Err(E) Yes
panic!Unrecoverable program failureNever returns No

Summary – Recap & Next Steps

Rust’s error system encourages you to write safe, predictable code. By using Result, Option, and proper error propagation, you build programs that fail gracefully and informatively.

Key Takeaways:

  • Use Option<T> when absence of value is expected
  • Use Result<T, E> for recoverable I/O and system errors
  • Use ? to simplify error propagation
  • Avoid unwrap() and panic! in production logic

Next: Learn about Generics and Traits to write reusable and type-safe Rust functions.


FAQs


What does the ? operator do in Rust?
It checks if a result is Err, and if so, returns it early from the function. Otherwise, it unwraps the Ok value.


When should I use Option instead of Result?
Use Option when there’s no meaningful error message—just “value or not.” Use Result when you want to return a specific error type.


Is unwrap() ever safe to use?
It can be used in controlled code (like tests), but in production logic, prefer match, ?, or expect() with custom messages.


Can I define custom error types in Rust?
Yes. Use enum and implement Display, Debug, and optionally std::error::Error.


Share Now :
Share

Rust Error Handling

Or Copy Link

CONTENTS
Scroll to Top