⚠️

Result and the ? Operator β€” Rust Error Handling Patterns

Handling errors as types without try-catch

Java/Python catch errors with try-catch. The problem: you can't tell from a function signature what exceptions it might throw. Rust puts errors inside the type system.

Result<T, E> β€” T is the success value, E the error. Looking at the signature tells you whether the function can fail and what error it returns.

fn read_file(path: &str) -> Result<String, io::Error> {
    let content = fs::read_to_string(path)?;
    Ok(content)
}

? is the key. On Err, return immediately; on Ok, extract the inner value. More concise than try-catch with explicit error propagation paths.

unwrap() panics (crashes) on error. Convenient for prototyping but forbidden in production.

Key Points

1

Fallible functions return Result<T, E>

2

? operator auto-propagates errors to the caller

3

Transform/handle errors with match or map_err

4

Define custom error types with thiserror/anyhow crates

Pros

  • Error possibility visible from function signature alone
  • Error propagation is concise with ? operator

Cons

  • Error type conversion (From trait) is tedious at first
  • Temptation to overuse unwrap is strong

Use Cases

File/network I/O β€” failure is part of normal flow CLI tools β€” gracefully display user input validation errors