{
    "slug": "rust_error_handling_result",
    "term": "Rust Error Handling with Result",
    "category": "rust",
    "difficulty": "beginner",
    "short": "Rust models recoverable errors as Result<T, E> values returned from functions, not thrown exceptions, with the ? operator for propagation.",
    "long": "Rust has no exceptions for recoverable errors. Instead, fallible functions return `Result<T, E>`, an enum with two variants: `Ok(T)` carrying a success value and `Err(E)` carrying an error. Because `Result` is `#[must_use]`, the compiler warns if you ignore it, forcing you to acknowledge that an operation can fail. This makes failure paths visible in type signatures rather than hidden in stack-unwinding control flow.\n\nTo extract a value you must handle both variants, typically with `match`, combinators like `map`, `and_then`, `unwrap_or`, or the `?` operator. The `?` operator is the idiomatic propagation tool: in a function returning `Result`, `let f = File::open(path)?;` returns early with the `Err` if the call failed, otherwise unwraps the `Ok` value. `?` also applies the `From` trait to convert the error into the function's declared error type, which is why error-handling crates and custom error enums implement `From` for their sources.\n\nA crucial distinction is `Result` versus `panic!`. `Result` is for expected, recoverable failures - a missing file, invalid input, a network timeout. `panic!` (and the `unwrap`/`expect` methods that trigger it) is for unrecoverable bugs and broken invariants. Reaching for `.unwrap()` everywhere turns recoverable errors into crashes and is a common beginner mistake. `.expect(\"reason\")` is marginally better because it documents the assumption, but production code on real input should propagate or handle, not unwrap.\n\nFor error types, libraries commonly use `thiserror` to derive rich enum errors with `Display` and `From` impls, while applications use `anyhow` for a boxed, context-carrying `Result` that is easy to propagate. The `Option<T>` type plays a parallel role for absence (`Some`/`None`) and converts to `Result` via `ok_or`. Combined with `?`, these tools let you write linear, readable code where the happy path dominates and errors flow upward explicitly, giving exhaustive, compiler-checked handling without the invisible control flow of exceptions.",
    "aliases": [
        "rust result type",
        "result and option",
        "question mark operator"
    ],
    "tags": [
        "rust",
        "error-handling",
        "result-type",
        "option-type",
        "question-mark-operator"
    ],
    "misconception": "Rust uses try/catch exceptions like other languages, and .unwrap() is the normal way to get a value out of a Result. In reality errors are ordinary return values, and unwrap turns a recoverable error into a panic that crashes the program.",
    "why_it_matters": "Overusing unwrap and expect converts handleable failures into crashes, while ignoring the #[must_use] Result silently drops errors, producing fragile services that panic on the first bad input in production.",
    "common_mistakes": [
        "Calling .unwrap() or .expect() on Results from fallible I/O or parsing, turning recoverable errors into runtime panics.",
        "Ignoring a returned Result and triggering only an unused-must-use warning instead of handling the failure.",
        "Writing nested match blocks to propagate errors when the ? operator would express the same thing in one line.",
        "Using panic! or .unwrap() for expected conditions like missing config rather than returning an Err.",
        "Returning a concrete error type from one source so ? cannot convert other error types, instead of a unifying enum or Box<dyn Error>."
    ],
    "when_to_use": [
        "Any function performing I/O, parsing, or network calls where failure is an expected runtime condition.",
        "Library APIs that should let callers decide how to handle failure rather than crashing their process.",
        "Propagating errors up a call stack concisely with ? while converting between error types via From.",
        "Building services that must stay alive and respond gracefully when individual requests or inputs are invalid."
    ],
    "avoid_when": [
        "Quick prototypes, examples, or tests where a panic on bad input is acceptable and explicit error types add noise.",
        "Cases where an Err genuinely represents an unrecoverable broken invariant, where panic! communicates the bug more honestly.",
        "Code where the value is statically guaranteed present, such as a constant literal parse, and expect documents the impossibility."
    ],
    "related": [
        "rust_traits",
        "early_return"
    ],
    "prerequisites": [
        "rust_traits"
    ],
    "refs": [
        "https://doc.rust-lang.org/book/ch09-00-error-handling.html",
        "https://doc.rust-lang.org/std/result/enum.Result.html",
        "https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator",
        "https://rust-lang.github.io/api-guidelines/interoperability.html#error-types-are-meaningful-and-well-behaved-c-good-err"
    ],
    "bad_code": "use std::fs::File;\nuse std::io::Read;\n\n// Returns the parsed number, but panics on every failure path.\nfn read_count(path: &str) -> u32 {\n    // unwrap panics if the file is missing.\n    let mut file = File::open(path).unwrap();\n    let mut contents = String::new();\n    // unwrap panics on a read error.\n    file.read_to_string(&mut contents).unwrap();\n    // unwrap panics if the contents are not a valid number.\n    contents.trim().parse::<u32>().unwrap()\n}\n\nfn main() {\n    // A missing file or garbage input crashes the whole program.\n    let count = read_count(\"count.txt\");\n    println!(\"{}\", count);\n}",
    "good_code": "use std::fs::File;\nuse std::io::{self, Read};\nuse std::num::ParseIntError;\n\n#[derive(Debug)]\nenum CountError {\n    Io(io::Error),\n    Parse(ParseIntError),\n}\n\n// From impls let the ? operator convert each source error automatically.\nimpl From<io::Error> for CountError {\n    fn from(e: io::Error) -> Self { CountError::Io(e) }\n}\nimpl From<ParseIntError> for CountError {\n    fn from(e: ParseIntError) -> Self { CountError::Parse(e) }\n}\n\n// Failure is visible in the signature; ? propagates errors cleanly.\nfn read_count(path: &str) -> Result<u32, CountError> {\n    let mut file = File::open(path)?;\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?;\n    let count = contents.trim().parse::<u32>()?;\n    Ok(count)\n}\n\nfn main() {\n    match read_count(\"count.txt\") {\n        Ok(count) => println!(\"{}\", count),\n        Err(e) => eprintln!(\"could not read count: {:?}\", e),\n    }\n}",
    "quick_fix": "Return Result<T, E> from fallible functions and propagate with ?, reserving unwrap/expect for genuinely impossible cases or quick prototypes.",
    "severity": "medium",
    "effort": "low",
    "created": "2026-06-05",
    "updated": "2026-06-05",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/rust_error_handling_result",
        "html_url": "https://codeclaritylab.com/glossary/rust_error_handling_result",
        "json_url": "https://codeclaritylab.com/glossary/rust_error_handling_result.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Rust Error Handling with Result](https://codeclaritylab.com/glossary/rust_error_handling_result) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/rust_error_handling_result"
            }
        }
    }
}