Rust's Two Error Types: Recoverable vs. Unrecoverable
Rust splits errors into two camps: recoverable (`Result`) and unrecoverable (`panic!`). This compile-time distinction forces you to handle expected failures, like a missing file, while crashing on programmer bugs, like an out-of-bounds access.
WHY IT EXISTS To build more robust software by forcing developers to confront potential failures at compile time, rather than discovering them as runtime exceptions in production. Rust separates bugs (unrecoverable errors) from operational failures (recoverable errors), demanding different handling for each.
THE MENTAL MODEL Think of errors in two distinct categories. First, expected failures that are part of normal operation, like a file not being found or a network connection dropping. Second, programmer mistakes that violate the program's own rules, like accessing an invalid array index. Rust provides Result for the former and panic! for the latter.
HOW IT WORKS For recoverable errors, functions return a Result<T, E> enum. This type has two possible variants: Ok(T), which holds a successful value of type T, or Err(E), which holds an error value of type E. The compiler ensures you handle both possibilities before your code can even run. For unrecoverable errors, the panic! macro is called. This immediately stops the current thread, unwinds and cleans up the stack, and typically exits the program with an error message. It signals a state so bad the program cannot safely continue.
WHEN TO USE IT Use Result<T, E> for any operation that might fail due to conditions outside your program's direct control. This includes I/O operations (reading files), network requests (API calls), parsing user input, or any other interaction with the outside world. This should be your default error handling mechanism.
WHEN NOT TO USE IT Do not use Result for situations that represent a bug in your code's logic. If a function's internal invariants are violated, a panic! is more appropriate because the program is in a state it was never designed to handle. Conversely, never use panic! for an expected failure like a "file not found" error. This makes your application fragile and non-resilient.
ONE CANONICAL EXAMPLE A function attempting to open a file returns Result<File, io::Error>. If the file exists, the function returns Ok(file_handle). If the file is not found, it returns Err(error_info), allowing the caller to decide how to proceed. In contrast, if you have a vector with 10 elements and try to access vec[10], Rust will panic!. This is a bug, not a predictable failure.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.