Error Handling Basics
8 examples - 5 basic, 3 intermediate - covering Option, Result, and when to panic.
Prerequisites
Basic Examples
1. Option for Missing Values
fn find(ids: &[u32], target: u32) -> Option<usize> {
ids.iter().position(|&id| id == target)
}Nonemeans not found without error detailSome(i)carries index- No null pointers
2. Result for Failures
use std::fs;
fn read(path: &str) -> Result<String, std::io::Error> {
fs::read_to_string(path)
}Errincludes error reasonOkon success- Recoverable errors use
Result
3. match on Result
fn main() {
match read("Cargo.toml") {
Ok(body) => println!("{body}"),
Err(e) => eprintln!("{e}"),
}
}4. unwrap and expect (prototypes)
let n: u32 = "42".parse().expect("valid port");- Panics on
Err- binaries/prototypes only - Libraries should return
Result
5. ? Propagation Preview
fn load() -> Result<String, std::io::Error> {
let s = std::fs::read_to_string("config.toml")?;
Ok(s)
}Related: The ? Operator
Intermediate Examples
6. Combine Option and Result
fn first_user(names: &[&str]) -> Result<&str, &'static str> {
names.first().ok_or("empty list")
}7. map and and_then
let port: Option<u16> = Some("8080")
.and_then(|s| s.parse().ok());8. Custom Error Enum Preview
enum AppError { Io(std::io::Error), Parse(std::num::ParseIntError) }Related: Error Handling Best Practices
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.