Lesson 16 / 25

Panics, unwrap and Safe Alternatives

Bugs stop the thread.

When panicking is appropriate

A panic stops the current thread with a message: out-of-bounds indexing, unwrap() on None or Err, integer overflow in debug builds, or an explicit panic!. Panics are for bugs and broken invariants, not expected failures. Prefer safe alternatives: get(i) returns an Option, unwrap_or supplies defaults, and expect("reason") documents why a value must exist. Unhandled panics in the main thread end the program with exit code 101.

Safe access versus a panicking index, run

I ran this with Rust 1.99.0 (cargo run, edition 2024, standard library only). get(10) returns None and unwrap_or supplies -1, but indexing v[10] panics with an index-out-of-bounds message and the program exits with status 101. The thread id was removed from the panic line.

fn main() {
    let v = vec![1, 2, 3];
    println!("get(10) = {:?}", v.get(10));   // safe: returns None
    let x: Option<i32> = None;
    println!("{}", x.unwrap_or(-1));
    let item = v[10];                         // panics: index out of bounds
    println!("{item}");
}

Output:

get(10) = None
-1

thread main panicked at src/main.rs:6:17:
index out of bounds: the len is 3 but the index is 10
exit status: 101

Use expect with a reason

If you must unwrap, expect("config loaded at startup") leaves a clear message when the assumption breaks.

Quick check: Which call avoids a panic when the index might be out of range?

  • v.unwrap()
  • v[i]
  • v.get(i)
  • panic!()
Answer

v.get(i) — get returns Option.