Bird
Raised Fist0
Rustprogramming~20 mins

Propagating errors with ? in Rust - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Rust Error Propagation Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output of this Rust code using the ? operator?

Consider this Rust function that reads a number from a string and doubles it. What will be printed when calling main()?

Rust
fn double_number(s: &str) -> Result<i32, std::num::ParseIntError> {
    let n: i32 = s.parse()?;
    Ok(n * 2)
}

fn main() {
    match double_number("10") {
        Ok(val) => println!("Result: {}", val),
        Err(e) => println!("Error: {}", e),
    }
}
AResult: 20
BResult: 10
CError: invalid digit found in string
DCompilation error due to missing match
Attempts:
2 left
💡 Hint

Remember that ? returns the error early if parsing fails, otherwise continues.

❓ Predict Output
intermediate
2:00remaining
What error does this Rust code raise when using the ? operator?

What happens when running this Rust code?

Rust
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
    let n: i32 = s.parse()?;
    Ok(n * 2)
}

fn main() {
    match parse_and_double("abc") {
        Ok(val) => println!("Result: {}", val),
        Err(e) => println!("Error: {}", e),
    }
}
APanic at runtime due to unwrap on Err
BError: invalid digit found in string
CCompilation error: cannot use ? outside function returning Result
DResult: 0
Attempts:
2 left
💡 Hint

What happens if parsing fails with ? inside a function returning Result?

🔧 Debug
advanced
2:00remaining
Why does this Rust code fail to compile when using the ? operator?

Examine this Rust code snippet. Why does it fail to compile?

Rust
fn try_parse(s: &str) {
    let n: i32 = s.parse()?;
    println!("Number: {}", n);
}

fn main() {
    try_parse("42");
}
Aparse() returns Option, not Result
BMissing semicolon after parse() call
CCannot use ? operator inside main function
DFunction try_parse must return Result to use ? operator
Attempts:
2 left
💡 Hint

The ? operator can only be used in functions that return Result or Option.

📝 Syntax
advanced
2:00remaining
Which option correctly propagates errors using the ? operator in Rust?

Choose the code snippet that correctly uses the ? operator to propagate errors.

A
fn read_number(s: &amp;str) -&gt; Result&lt;i32, std::num::ParseIntError&gt; {
    let n = s.parse()?;
    Ok(n)
}
B
fn read_number(s: &amp;str) -&gt; i32 {
    let n = s.parse()?;
    n
}
C
fn read_number(s: &amp;str) -&gt; Result&lt;i32, std::num::ParseIntError&gt; {
    let n = s.parse().unwrap();
    Ok(n)
}
D
fn read_number(s: &amp;str) -&gt; Result&lt;i32, std::num::ParseIntError&gt; {
    let n = s.parse();
    Ok(n?)
}
Attempts:
2 left
💡 Hint

Remember that ? can only be used on a Result or Option value directly.

🚀 Application
expert
3:00remaining
How many times is the error propagated in this Rust code using multiple ? operators?

Given this Rust code, how many times will the error be propagated if the input string is invalid?

Rust
fn step1(s: &str) -> Result<i32, std::num::ParseIntError> {
    let n = s.parse()?;
    Ok(n)
}

fn step2(s: &str) -> Result<i32, std::num::ParseIntError> {
    let n = step1(s)?;
    Ok(n * 2)
}

fn main() {
    match step2("not_a_number") {
        Ok(val) => println!("Value: {}", val),
        Err(e) => println!("Error: {}", e),
    }
}
AThe error is propagated twice inside step1 before returning
BThe error is caught and handled inside step1, so no propagation
CThe error is propagated once from step1 to step2, then to main
DThe error causes a panic and does not propagate
Attempts:
2 left
💡 Hint

Think about how the ? operator passes errors up the call stack.

Practice

(1/5)
1. What does the ? operator do in Rust when used with a Result type?
easy
A. It ignores any error and always returns the success value.
B. It converts the Result into an Option.
C. It returns the error immediately if there is one, otherwise unwraps the value.
D. It retries the operation until it succeeds.

Solution

  1. Step 1: Understand the ? operator behavior

    The ? operator checks if the Result is an Err. If yes, it returns the error from the current function immediately.
  2. Step 2: What happens if Result is Ok?

    If the Result is Ok, it unwraps the value inside and continues execution.
  3. Final Answer:

    It returns the error immediately if there is one, otherwise unwraps the value. -> Option C
  4. Quick Check:

    ? returns error or unwraps value [OK]
Hint: Remember: ? returns error early or unwraps success [OK]
Common Mistakes:
  • Thinking ? converts Result to Option
  • Assuming ? ignores errors
  • Believing ? retries operations
2. Which of the following function signatures correctly allows using the ? operator inside the function to propagate std::io::Error?
easy
A. fn read_file() -> String
B. fn read_file() -> Result
C. fn read_file() -> ()
D. fn read_file() -> Option<String>

Solution

  1. Step 1: Identify return types compatible with ?

    The ? operator works only in functions returning Result or Option.
  2. Step 2: Check each signature

    fn read_file() -> String returns String directly, no error type, so ? can't be used. fn read_file() -> Result returns Result, which supports ?. fn read_file() -> () returns unit (), no error handling. fn read_file() -> Option<String> returns Option, which supports ? for absence but cannot propagate std::io::Error.
  3. Final Answer:

    fn read_file() -> Result -> Option B
  4. Quick Check:

    Function must return Result or Option for ? [OK]
Hint: Use Result or Option return type to use ? [OK]
Common Mistakes:
  • Using ? in functions returning plain types
  • Forgetting to specify error type in Result
  • Confusing Option and Result return types
3. What is the output of the following Rust code?
fn parse_number(s: &str) -> Result {
    let num = s.parse::<i32>()?;
    Ok(num * 2)
}

fn main() {
    match parse_number("10") {
        Ok(n) => println!("{}", n),
        Err(e) => println!("Error: {}", e),
    }
}
medium
A. 20
B. Error: invalid digit found in string
C. 10
D. Compilation error

Solution

  1. Step 1: Understand parse_number function

    The function tries to parse the string "10" to an integer using s.parse::<i32>()?. Since "10" is valid, it unwraps to 10.
  2. Step 2: Calculate the returned value

    It multiplies the parsed number by 2, so 10 * 2 = 20, then returns Ok(20).
  3. Step 3: Check main output

    The match prints the number 20 because parsing succeeded.
  4. Final Answer:

    20 -> Option A
  5. Quick Check:

    Valid parse returns doubled number [OK]
Hint: Valid parse with ? returns doubled value [OK]
Common Mistakes:
  • Assuming parse fails and prints error
  • Confusing output with input string
  • Thinking code won't compile due to ?
4. Identify the error in this Rust function using ? and fix it:
fn get_first_char(s: &str) -> Result {
    let first = s.chars().next()?;
    Ok(first)
}
medium
A. Change next() to next().ok_or("Empty string".to_string())?
B. Change return type to Option<char>
C. Replace ? with .unwrap()
D. No error, code is correct

Solution

  1. Step 1: Analyze next() return type

    next() returns an Option<char>, but ? requires Result or Option compatible with function return.
  2. Step 2: Fix error propagation

    Since function returns Result, convert Option to Result using next().ok_or("Empty string".to_string())? to propagate error properly.
  3. Final Answer:

    Change next() to next().ok_or("Empty string".to_string())? -> Option A
  4. Quick Check:

    Convert Option to Result for ? in Result function [OK]
Hint: Convert Option to Result with ok_or before ? [OK]
Common Mistakes:
  • Using ? directly on Option in Result function
  • Ignoring error conversion from Option to Result
  • Replacing ? with .unwrap() causing panic
5. You want to write a function that reads a file and returns the number of lines. It should propagate any IO errors using ?. Which of the following implementations correctly uses ? to propagate errors?
hard
A. fn count_lines(path: &str) -> Option<usize> { let content = std::fs::read_to_string(path)?; Some(content.lines().count()) }
B. fn count_lines(path: &str) -> usize { let content = std::fs::read_to_string(path)?; content.lines().count() }
C. fn count_lines(path: &str) -> Result { let content = std::fs::read_to_string(path).unwrap(); Ok(content.lines().count()) }
D. fn count_lines(path: &str) -> Result { let content = std::fs::read_to_string(path)?; Ok(content.lines().count()) }

Solution

  1. Step 1: Check function return type compatibility

    The function returns Result, so it can use ? to propagate IO errors.
  2. Step 2: Analyze each option

    fn count_lines(path: &str) -> Result { let content = std::fs::read_to_string(path)?; Ok(content.lines().count()) } uses ? correctly and returns Ok with line count. fn count_lines(path: &str) -> usize { let content = std::fs::read_to_string(path)?; content.lines().count() } returns usize directly but uses ? which is invalid here. fn count_lines(path: &str) -> Result { let content = std::fs::read_to_string(path).unwrap(); Ok(content.lines().count()) } uses unwrap() which panics on error, not propagates. fn count_lines(path: &str) -> Option<usize> { let content = std::fs::read_to_string(path)?; Some(content.lines().count()) } returns Option but read_to_string returns Result, so ? cannot be used directly.
  3. Final Answer:

    fn count_lines(path: &str) -> Result<usize, std::io::Error> { let content = std::fs::read_to_string(path)?; Ok(content.lines().count()) } -> Option D
  4. Quick Check:

    Return Result and use ? to propagate errors [OK]
Hint: Match function return type with ? usage for error propagation [OK]
Common Mistakes:
  • Using ? in functions without Result or Option return
  • Using unwrap() instead of propagating errors
  • Mismatching return types and error handling
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard