tezvyn:

Handling Errors with Rust's Result Enum

AI-drafted, machine-checkedSource: doc.rust-lang.orgbeginner

Rust's `Result` enum makes error handling explicit. Instead of returning a value that might be an error code, functions return either `Ok(value)` or `Err(error)`. It's used for recoverable failures like I/O.

WHY IT EXISTS To prevent bugs from ignored errors. In many languages, functions signal errors with special return values (like -1 or null) that are easy to forget to check. Rust's Result type, combined with the compiler's #[must_use] check, issues a warning if a potential failure is not handled, making errors explicit.

THE MENTAL MODEL Think of Result<T, E> as a sealed box that contains either a successful outcome (Ok(T)) or a failure (Err(E)). To get the value out, you must explicitly open the box and acknowledge both possibilities. This moves error handling from a runtime discipline problem to a compile-time requirement.

HOW IT WORKS Result is an enum with two variants: Ok(T) for a success value of type T, and Err(E) for an error of type E. You can handle it with a match expression to explicitly branch your code for each case. For more concise handling, Rust provides methods like is_ok(), map(), and and_then(). The most idiomatic tool is the question mark operator (?). Placing ? after a function call that returns a Result will either unwrap the Ok value and continue, or immediately return the Err from the current function, propagating the error up the call stack.

WHEN TO USE IT Use Result for any error that is expected and recoverable. This is the standard for almost all fallible operations in Rust, such as file I/O (a file might not exist), network requests (a server might be down), or data parsing (input might be malformed).

WHEN NOT TO USE IT For unrecoverable errors, a panic! is more appropriate. These represent bugs in the program logic, like an out-of-bounds array access, where continuing execution is impossible or nonsensical. Result is for expected, handleable failures; panic! is for unexpected, catastrophic ones.

ONE CANONICAL EXAMPLE A function parsing a version number from a byte stream returns a Result. If the first byte is 1, it returns Ok(Version::Version1). If the header is empty, it returns Err("invalid header length"). The calling code must then use a match or ? to handle both the success and error cases, preventing an unhandled error from going unnoticed.

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.