Skip to content

The Result Type

Result<T, E> is the standard Rust type for operations that can either succeed or fail in an expected way. It is defined in the standard library as:

enum Result<T, E> {
Ok(T),
Err(E),
}
  • Ok(T) — the operation succeeded and produced a value of type T.
  • Err(E) — the operation failed and produced an error value of type E.

Both T and E are generic parameters you fill in. For example, Result<i32, String> succeeds with an i32 or fails with a String error message.

To signal a recoverable failure from a function, change its return type to Result<T, E> and return Ok(value) on success or Err(error) on failure:

fn parse_age(s: &str) -> Result<u32, String> {
s.parse::<u32>().map_err(|e| format!("parse error: {}", e))
}

The .map_err call converts the standard library’s parse error into your own String error type.

The most explicit way to handle a Result is a match expression — it forces you to address both branches:

fn parse_age(s: &str) -> Result<u32, String> {
s.parse::<u32>().map_err(|e| format!("parse error: {}", e))
}
fn main() {
match parse_age("25") {
Ok(age) => println!("Parsed age: {}", age),
Err(e) => println!("Error: {}", e),
}
}

For less verbose code, Result provides several methods:

MethodBehaviour
.unwrap()Returns the Ok value; panics on Err
.expect(msg)Same, but with a custom panic message
.unwrap_or(default)Returns the Ok value or a default
.unwrap_or_else(|e| ...)Returns the Ok value or computes a default from the error
.is_ok() / .is_err()Boolean tests without extracting the value
.map(|v| ...)Transforms the Ok value, leaves Err unchanged
.map_err(|e| ...)Transforms the Err value, leaves Ok unchanged
fn parse_age(s: &str) -> Result<u32, String> {
s.parse::<u32>().map_err(|e| format!("parse error: {}", e))
}
fn main() {
// Match on Result to handle both branches
match parse_age("25") {
Ok(age) => println!("Parsed age: {}", age),
Err(e) => println!("Error: {}", e),
}
// .unwrap_or returns a default on Err
let age1 = parse_age("abc").unwrap_or(0);
println!("unwrap_or default: {}", age1);
// .unwrap_or_else lets you compute the default
let age2 = parse_age("not_a_number").unwrap_or_else(|e| {
println!("Recovering from: {}", e);
18
});
println!("unwrap_or_else result: {}", age2);
// is_ok / is_err for simple checks
println!("parse_age(\"30\") is_ok: {}", parse_age("30").is_ok());
println!("parse_age(\"xx\") is_err: {}", parse_age("xx").is_err());
}
What are the two variants of Result<T, E>?
What does .unwrap_or_else(|e| ...) do when the Result is Err(e)?
Which method transforms the Ok value without touching the Err?
Why does the Rust compiler warn when a Result is unused?