Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. Result<T, E> / Ok / Err

Result<T, E> / Ok / Err

Since: Rust 1.0(2015)

Result<T, E> is an enum that represents the outcome of an operation as either success (Ok) or failure (Err). Instead of exceptions, Rust uses Result to force you to handle potential errors at compile time.

Syntax

// Wrap a success value in Ok.
let ok: Result<i32, String> = Ok(42);

// Wrap an error value in Err.
let err: Result<i32, String> = Err(String::from("An error occurred."));

// Use match to branch on success or failure.
match result {
    Ok(value) => println!("Success: {}", value),
    Err(e) => println!("Failure: {}", e),
}

// Use if let to handle only the success case.
if let Ok(value) = result {
    println!("Success: {}", value);
}

Syntax reference

Syntax / VariantDescription
Ok(value)A variant indicating that the operation succeeded. Holds the resulting success value.
Err(error)A variant indicating that the operation failed. Holds details about the error. Any type can be used as the error type.
matchBranches on the two patterns Ok(v) and Err(e). Both arms are required, preventing you from accidentally ignoring errors.
if let Ok(v)Syntactic sugar for handling only the success case. Overusing it can lead to missed errors, as it silently ignores the Err case.
is_ok() / is_err()Returns a boolean indicating whether the result is a success or failure. Use these when you only need to check the state without processing the value.

Sample code

sample_result_ok_err.rs
// A function that divides two numbers and returns Err on division by zero.
fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err(String::from("Cannot divide by zero."))
    } else {
        Ok(a / b)
    }
}

fn main() {
    // Handle the success case with match.
    match divide(10.0, 2.0) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }

    // Handle the failure case with match.
    match divide(10.0, 0.0) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }

    // Check the state with is_ok / is_err.
    let r1 = divide(10.0, 2.0);
    let r2 = divide(10.0, 0.0);
    println!("r1 is_ok: {}", r1.is_ok()); // true
    println!("r2 is_err: {}", r2.is_err()); // true

    // Parsing from the standard library also returns a Result.
    let parsed: Result<i32, _> = "42".parse();
    println!("{:?}", parsed); // Ok(42)

    let failed: Result<i32, _> = "abc".parse();
    println!("{:?}", failed); // Err(...)
}

Compile with the following command:

rustc result_ok_err.rs
./result_ok_err
Result: 5
Error: Cannot divide by zero.
r1 is_ok: true
r2 is_err: true
Ok(42)
Err(ParseIntError { kind: InvalidDigit })

Common Mistakes

Mistake 1: Discarding a Result and getting a compiler warning

If you drop the return value of a function that returns Result without using it, the compiler will issue a warning. Because the error is silently ignored, this can cause problems in production.

result_mistake1.rs
use std::fs;

fn main() {
    // Ignoring the Result produces a compiler warning.
    fs::remove_file("nonexistent.txt");
    println!("Done");
}

Compile with the following command:

rustc result_mistake1.rs
warning: unused `Result` that must be used
  --> result_mistake1.rs:5:5

Either handle the Result explicitly, or use let _ = to signal that ignoring it is intentional.

result_fix1.rs
use std::fs;

fn main() {
    // Handle with match.
    match fs::remove_file("nonexistent.txt") {
        Ok(_) => println!("Deleted"),
        Err(e) => println!("Delete failed: {}", e),
    }

    // Use let _ = to explicitly signal intentional ignoring.
    let _ = fs::remove_file("already_gone.txt");
}

Compile with the following command:

rustc result_fix1.rs
./result_fix1
Delete failed: No such file or directory (os error 2)

Mistake 2: Overusing unwrap() and causing a panic

unwrap() panics when the value is Err. Unless you are certain that an error cannot occur, handle the result properly using match, if let, or the ? operator.

result_mistake2.rs
fn main() {
    // Calling unwrap() on user input is risky.
    let input = "abc"; // not a number
    let n: i32 = input.parse().unwrap(); // panic!
    println!("{}", n);
}

Compile with the following command:

rustc result_mistake2.rs
./result_mistake2
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }'

Use unwrap_or(), unwrap_or_else(), or match to handle the error.

result_fix2.rs
fn parse_score(s: &str) -> i32 {
    s.parse::<i32>().unwrap_or_else(|e| {
        println!("Parse failed '{}': {} -> using 0", s, e);
        0
    })
}

fn main() {
    println!("{}", parse_score("95")); // 95
    println!("{}", parse_score("abc")); // parse failed -> 0
    println!("{}", parse_score("-5")); // -5
}

Compile with the following command:

rustc result_fix2.rs
./result_fix2
95
Parse failed 'abc': invalid digit found in string -> using 0
0
-5

Notes

In the type parameter Result<T, E>, T is the type of the success value and E is the type of the error value. You can use any type for the error, such as the standard library's std::io::Error or a custom type. If you discard the return value of a function that returns Result without using it, the compiler will issue a warning. Errors must always be handled explicitly or explicitly ignored.

Almost every operation in Rust's standard library that can fail — file I/O, networking, parsing, and more — returns a Result. This is the Rust equivalent of try-catch in other languages. Because Rust has no exceptions, treating errors as explicit return values is the idiomatic Rust approach.

If you find any errors or copyright issues, please .