🚀
8. Error Handling
Languages

Error Handling

- Rust has a robust error handling system

Mar 202510 min read

Error Handling

  • Rust has a robust error handling system

Panic

  • Rust has a panic! macro to stop the program when an error occurs
fn main() {
    panic!("crash and burn");
}
Execution Output
Runtime Error:
thread 'main' panicked at 'crash and burn', src/main.rs:2:5
  • panic! macro can be used to generate a backtrace

Result Enum

  • Rust uses the Result enum to handle errors
use std::fs::File;
 
fn main() {
    let f = File::open("hello.txt");
 
    let f = match f {
        Ok(file) => file,
        Err(error) => {
            panic!("Problem opening the file: {:?}", error)
        },
    };
}
  • match keyword is used to handle the Result enum
  • Result has two variants: Ok and Err
  • Ok variant indicates success and contains a value
  • Err variant indicates failure and contains an error message
use std::{fs::File, io::ErrorKind};
 
fn main() {
    let f = File::open("hello.txt");
 
    let f = match f {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            },
            other_error => {
                panic!("Problem opening the file: {:?}", other_error)
            }
        },
    };
}
  • Nested match expressions can be used to handle different error types
  • ErrorKind enum is used to handle different error types
  • when ErrorKind is NotFound, create is used to create the file named hello.txt

Closure

  • Rust has a unwrap method to handle errors
use std::fs::File;
fn main() {
      let f = File::open("hello.txt").unwrap_or_else(|error| {
        if error.kind() == ErrorKind::NotFound {
            File::create("hello.txt").unwrap_or_else(|error| {
                panic!("Problem creating the file: {:?}", error);
            })
        } else {
            panic!("Problem opening the file: {:?}", error);
        }
    });
}
  • unwrap_or_else method is used to handle errors

Expect

  • Rust has an expect method to handle errors
use std::fs::File;
fn main() {
    let f = File::open("hello.txt").expect("Failed to open the file");
}

? Operator

  • Rust has a ? operator to handle errors
 
use std::fs::File;
use std::io;
use std::io::Read;
 
fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("hello.txt");
 
    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };
 
    let mut s = String::new();
 
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}
 
fn main() {}
  • ? operator is used to handle errors
use std::fs::File;
use std::io;
use std::io::Read;
 
fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("hello.txt")?;
 
    let mut s = String::new();
 
    f.read_to_string(&mut s)?;
 
    Ok(s)
}
 
fn main() {}
  • ? operator can be used to handle errors in a more concise way
  • f.read_to_string(&mut s)? will return Ok(s) if successful, otherwise it will return Err(e)
use std::fs::File;
use std::io;
use std::io::Read;
 
fn read_username_from_file() -> Result<String, io::Error> {
    let mut s = String::new();
    File::open("hello.txt")?.read_to_string(&mut s)?;
 
    Ok(s)
}
 
fn main() {}
 
  • ? operator can be chained to handle errors in a more concise way
  • File::open("hello.txt")?.read_to_string(&mut s)? will return Ok(s) if successful, otherwise it will return Err(e)
use std::fs::File;
use std::io;
use std::io::Read;
 
fn main() {
    let mut s = String::new();
    File::open("hello.txt")?.read_to_string(&mut s)?;
 
    Ok(s)
}
Execution Output
the ? operator can only be used in a function that returns Result or
Option (or another type that implements FromResidual)
use std::fs::File;
use std::io;
use std::io::Read;
 
fn main() -> Result<(), io::Error> {
    let mut s = String::new();
    File::open("hello.txt")?.read_to_string(&mut s)?;
 
    Ok(())
}
  • ? operator can only be used in a function that returns Result or Option
  • main function returns Result with Ok variant

Panic vs Result vs Expect

  • In general the default should be using the Result enum and error propagation, prevents the program from crashing, and error propagation allows the caller to decide how to handle the error

  • panic! macro should be used when the program is in an unrecoverable state, used in example code, or when the program is in a state where it's not possible to recover

  • expect! method is used in prototype code, quick tests (when the program is in a state where it's not possible to recover)

  • unwrap! method is used in prototype code, when something is expected to be Ok but fails

Creating Custom Types for Validation

  • Rust allows creating custom types for validation
loop {
    let guess: i32 = match guess.trim().parse() {
        Ok(num) => num,
        Err(_) => continue,
    };
 
    if guess < 1 || guess > 100 {
        println!("The secret number will be between 1 and 100.");
        continue;
    }
 
    match guess.cmp(&secret_number) {
        // --snip--
    }
}
  • this works here, but doesn't scale well
struct Guess {
    value: i32,
}
 
impl Guess {
    fn new(value: i32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
 
        Guess { value }
    }
 
    fn value(&self) -> i32 {
        self.value
    }
}
  • this is a better way to handle validation

© 2026 Driptanil Datta. All rights reserved.

Software Developer & Engineer

Disclaimer:The content provided on this blog is for educational and informational purposes only. While I strive for accuracy, all information is provided "as is" without any warranties of completeness, reliability, or accuracy. Any action you take upon the information found on this website is strictly at your own risk.

Copyright & IP:Certain technical content, interview questions, and datasets are curated from external educational sources to provide a centralized learning resource. Respect for original authorship is maintained; no copyright infringement is intended. All trademarks, logos, and brand names are the property of their respective owners.

System Operational

Built with Love ❤️ | Last updated: Mar 16 2026