How does Rust handle errors with the Result type and the ? operator?
Understand how Rust handles errors with Result<T, E>, Ok and Err, and how the ? operator propagates and converts errors for clean, safe code.
Expected Interview Answer
Rust models recoverable errors with the Result<T, E> enum — Ok(value) on success or Err(error) on failure — and the ? operator propagates an Err early out of a function while unwrapping Ok, letting you write clean happy-path code without manual match blocks.
Because a fallible operation returns Result rather than throwing, callers must acknowledge failure to get at the value. Writing let x = something()?; means: if the result is Ok, bind the inner value to x; if it is Err, return that error from the current function immediately. The ? operator also runs the error through the From trait, converting it into the function's declared error type, which makes chaining fallible calls concise and type-safe.
- Errors are values, not hidden exceptions
- Failure is visible in every function's return type
- ? removes repetitive match boilerplate
- Automatic error conversion via the From trait
- The compiler warns on ignored Results
AI Mentor Explanation
Result is an appeal to the umpire: every fallible ball returns either Ok, meaning play continues, or Err, meaning a dismissal is signalled. The ? operator is the batter walking off the moment out is given — control leaves the crease immediately rather than pretending to carry on — so the innings only proceeds while each delivery keeps returning the Ok verdict.
Step-by-Step Explanation
Step 1
Return Result
Make fallible functions return Result<T, E> so success and failure are both explicit in the signature.
Step 2
Construct Ok or Err
Return Ok(value) on success and Err(error) describing what went wrong, instead of throwing.
Step 3
Propagate with ?
Append ? to a fallible call to unwrap Ok or return the Err from the current function immediately.
Step 4
Convert error types
Rely on the From trait so ? auto-converts a lower-level error into the function's declared error type.
Step 5
Handle at the boundary
At the top level use match, unwrap_or_else, or return Result from main to deal with the final error.
What Interviewer Expects
- Knowing Result<T, E> has Ok and Err variants
- Explaining what ? does on Ok versus Err
- Awareness that ? uses From for error conversion
- Contrast with exceptions in other languages
- Mentioning that Result is must-use
Common Mistakes
- Confusing Result with Option
- Thinking ? works only in main (it needs a Result or Option returning fn)
- Ignoring a Result and missing the compiler warning
- Overusing unwrap instead of propagating with ?
Best Answer (HR Friendly)
“Instead of throwing exceptions, Rust returns a Result that is either a success or an error, so failure is part of the function's contract. The question-mark operator is a shortcut that says 'if this failed, stop and pass the error up; otherwise give me the value', which keeps the main logic clean and readable.”
Code Example
use std::num::ParseIntError;
fn double_number(text: &str) -> Result<i32, ParseIntError> {
// ? returns the Err early if parsing fails, else unwraps the Ok value
let n = text.parse::<i32>()?;
Ok(n * 2)
}
fn main() {
match double_number("21") {
Ok(value) => println!("Doubled: {value}"),
Err(e) => println!("Error: {e}"),
}
match double_number("oops") {
Ok(value) => println!("Doubled: {value}"),
Err(e) => println!("Error: {e}"),
}
}Follow-up Questions
- How does the ? operator convert error types using From?
- What is the difference between Result and Option?
- How do crates like anyhow and thiserror improve error handling?
- Can you use ? in a function that returns Option?
MCQ Practice
1. What are the two variants of Result<T, E>?
Result<T, E> is Ok(value) on success or Err(error) on failure.
2. What does the ? operator do when applied to an Err value?
On Err, ? returns that error from the enclosing function, first converting it into the function's declared error type via the From trait; on Ok it unwraps the value.
Flash Cards
Rust's recoverable-error type — Result<T, E> with Ok(value) and Err(error).
What ? does on Ok — Unwraps and yields the inner value to continue.
What ? does on Err — Returns the error early, converting it via the From trait.
Result vs Option — Result carries a failure reason (Err); Option only signals absence (None).