Bird
Raised Fist0
Rustprogramming~20 mins

Error handling best practices in Rust - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Rust Error Handling 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 Result?

Consider this Rust code that tries to parse a number from a string and handle errors:

fn parse_number(s: &str) -> Result {
    s.parse::().map_err(|_| "Parse error".to_string())
}

fn main() {
    match parse_number("42") {
        Ok(n) => println!("Number: {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

What will this program print when run?

Rust
fn parse_number(s: &str) -> Result<i32, String> {
    s.parse::<i32>().map_err(|_| "Parse error".to_string())
}

fn main() {
    match parse_number("42") {
        Ok(n) => println!("Number: {}", n),
        Err(e) => println!("Error: {}", e),
    }
}
ANumber: 0
BError: Parse error
CNumber: 42
DCompilation error
Attempts:
2 left
💡 Hint

Think about what parse::() returns when given a valid number string.

❓ Predict Output
intermediate
2:00remaining
What error does this Rust code produce?

Look at this Rust code snippet:

fn main() {
    let v = vec![1, 2, 3];
    println!("{}", v[10]);
}

What happens when you run this program?

Rust
fn main() {
    let v = vec![1, 2, 3];
    println!("{}", v[10]);
}
AIndex out of bounds panic at runtime
BCompilation error: index out of bounds
CPrints 10
DPrints 0
Attempts:
2 left
💡 Hint

Think about how Rust handles accessing vector elements with an invalid index.

🧠 Conceptual
advanced
2:00remaining
Which Rust error handling practice is recommended for library code?

When writing a Rust library, which error handling approach is best practice?

AUse <code>panic!</code> to stop execution on errors
BReturn <code>Result</code> types to allow caller to handle errors
CIgnore errors and return default values
DUse <code>unwrap()</code> to simplify code
Attempts:
2 left
💡 Hint

Think about how libraries should behave to be flexible for users.

❓ Predict Output
advanced
2:00remaining
What is the output of this Rust code using ? operator?

Consider this Rust function:

fn get_first_char(s: &str) -> Result {
    let c = s.chars().next().ok_or("Empty string".to_string())?;
    Ok(c)
}

fn main() {
    match get_first_char("") {
        Ok(c) => println!("First char: {}", c),
        Err(e) => println!("Error: {}", e),
    }
}

What will this program print?

Rust
fn get_first_char(s: &str) -> Result<char, String> {
    let c = s.chars().next().ok_or("Empty string".to_string())?;
    Ok(c)
}

fn main() {
    match get_first_char("") {
        Ok(c) => println!("First char: {}", c),
        Err(e) => println!("Error: {}", e),
    }
}
APanic at runtime
BFirst char:
CCompilation error
DError: Empty string
Attempts:
2 left
💡 Hint

What does ok_or do when the iterator is empty?

🔧 Debug
expert
3:00remaining
Why is this Rust code problematic?

Examine this Rust code snippet:

fn read_file() -> Result {
    let content = std::fs::read_to_string("file.txt").unwrap();
    Ok(content)
}

Why is this not recommended when used in a function that returns Result?

Rust
fn read_file() -> Result<String, std::io::Error> {
    let content = std::fs::read_to_string("file.txt").unwrap();
    Ok(content)
}
AThe function should propagate errors using the <code>?</code> operator instead of <code>unwrap()</code>
BUsing <code>unwrap()</code> causes a panic and is not allowed in functions returning Result
CThe <code>read_to_string</code> function does not return a Result
DThe function must return <code>Option</code> instead of <code>Result</code>
Attempts:
2 left
💡 Hint

Think about how to properly propagate errors in functions returning Result.

Practice

(1/5)
1. What is the primary purpose of using Result in Rust error handling?
easy
A. To convert a string into a number
B. To represent either success or failure of an operation
C. To define a constant value in the program
D. To create a new thread for parallel execution

Solution

  1. Step 1: Understand the role of Result

    Result is an enum used to represent either success (Ok) or failure (Err) in Rust operations.
  2. Step 2: Identify the purpose in error handling

    It helps safely handle errors by forcing the programmer to consider both success and failure cases explicitly.
  3. Final Answer:

    To represent either success or failure of an operation -> Option B
  4. Quick Check:

    Result = success or failure [OK]
Hint: Result means success or error outcome [OK]
Common Mistakes:
  • Confusing Result with threading or constants
  • Thinking Result automatically fixes errors
  • Using Result only for numbers or strings
2. Which of the following is the correct syntax to use the ? operator in a function that returns Result<T, E>?
easy
A. let value = some_function()?;
B. let value = some_function!();
C. let value = some_function();?
D. let value = ?some_function();

Solution

  1. Step 1: Recall the ? operator usage

    The ? operator is placed immediately after a function call that returns a Result to propagate errors easily.
  2. Step 2: Check syntax correctness

    let value = some_function()?; correctly places ? after the function call: some_function()?. Other options misuse the operator placement.
  3. Final Answer:

    let value = some_function()?; -> Option A
  4. Quick Check:

    ? goes right after function call [OK]
Hint: Put ? right after the function call [OK]
Common Mistakes:
  • Placing ? before the function call
  • Using ! instead of ?
  • Adding ? after semicolon
3. What will be the output of this Rust code snippet?
fn divide(a: i32, b: i32) -> Result {
    if b == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(a / b)
    }
}

fn main() {
    match divide(10, 0) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }
}
medium
A. Result: 0
B. Panic at runtime
C. Error: division by zero
D. No output

Solution

  1. Step 1: Analyze the divide function call

    The function is called with b = 0, triggering the error branch returning Err("division by zero").
  2. Step 2: Check the match handling in main

    The Err case prints "Error: division by zero" to the console.
  3. Final Answer:

    Error: division by zero -> Option C
  4. Quick Check:

    Error message prints on zero divisor [OK]
Hint: Check if divisor is zero to get error output [OK]
Common Mistakes:
  • Assuming division returns 0 instead of error
  • Expecting panic instead of handled error
  • Ignoring match arms
4. Identify the error in this Rust code snippet related to error handling:
fn read_file() -> Result {
    let content = std::fs::read_to_string("file.txt");
    Ok(content)
}
medium
A. File path should be a variable, not a string literal
B. Function should return String not Result
C. Using Ok instead of Err
D. Missing ? operator to propagate error

Solution

  1. Step 1: Understand the return type and function call

    The function returns Result<String, std::io::Error>, but read_to_string returns a Result itself.
  2. Step 2: Identify missing error propagation

    The code assigns content as a Result but wraps it again in Ok without handling errors. The ? operator is needed to propagate errors properly.
  3. Final Answer:

    Missing ? operator to propagate error -> Option D
  4. Quick Check:

    Use ? to handle Result errors [OK]
Hint: Use ? to unwrap or propagate Result errors [OK]
Common Mistakes:
  • Wrapping Result inside Ok again
  • Ignoring error propagation
  • Changing return type incorrectly
5. You want to write a function that reads two files and returns the combined content as a String. Which is the best way to handle errors using Result and the ? operator? Choose the correct implementation:
fn read_two_files() -> Result {
    // Option A
    let content1 = std::fs::read_to_string("file1.txt")?;
    let content2 = std::fs::read_to_string("file2.txt")?;
    Ok(content1 + &content2)

    // Option B
    let content1 = std::fs::read_to_string("file1.txt").unwrap();
    let content2 = std::fs::read_to_string("file2.txt").unwrap();
    Ok(content1 + &content2)

    // Option C
    let content1 = std::fs::read_to_string("file1.txt").expect("file1 missing");
    let content2 = std::fs::read_to_string("file2.txt").expect("file2 missing");
    Ok(content1 + &content2)

    // Option D
    let content1 = std::fs::read_to_string("file1.txt");
    let content2 = std::fs::read_to_string("file2.txt");
    Ok(content1.unwrap() + &content2.unwrap())
}
hard
A. Use ? operator to propagate errors cleanly
B. Use unwrap() which panics on error
C. Use expect() which panics with message
D. Call unwrap() on Result without error handling

Solution

  1. Step 1: Understand error propagation best practice

    Using the ? operator propagates errors to the caller without panicking, making the function safe and clear.
  2. Step 2: Compare with other options

    The other options use unwrap() or expect(), which cause the program to panic on error, not recommended for robust error handling.
  3. Final Answer:

    Use ? operator to propagate errors cleanly -> Option A
  4. Quick Check:

    ? propagates errors safely [OK]
Hint: Use ? to avoid panics and propagate errors [OK]
Common Mistakes:
  • Using unwrap or expect causing panics
  • Not propagating errors properly
  • Ignoring error handling for multiple calls
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