Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

Rust Panic

A panic is Rust's emergency stop. When a program reaches a situation it cannot possibly continue from, it stops at once, prints a message saying what went wrong and where, and ends. It is not a crash in the scary sense: the program does not read random memory or carry on with nonsense values. It stops cleanly and tells you the truth.

Your first panic

You can cause one yourself with the panic! macro. Real programs rarely do this directly, but it shows exactly what a panic looks like:

fn main() {
    println!("Starting...");
    panic!("something impossible happened");
}
Output
Starting...
thread 'main' panicked at main.rs:3:5:
something impossible happened
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Read the message from the top. panicked at main.rs:3:5 means file main.rs, line 3, column 5. Then comes the reason. The last line is about a backtrace, a list of the functions that led here, which helps in bigger programs. A program that panics ends with exit code 101, the code Rust uses to say "this program panicked".

Common causes

In practice, most panics come from a few familiar places:

  • An index past the end: v[10] on a vector of three items.
  • unwrap on nothing: None.unwrap() or unwrap() on an Err.
  • Arithmetic problems: dividing a whole number by zero, or an overflow while the program runs.
fn main() {
    let marks = vec![70, 85, 92];
    let position = marks.len();
    println!("Looking at position {}", position);
    println!("{}", marks[position]);
}
Output
Looking at position 3
thread 'main' panicked at main.rs:5:25:
index out of bounds: the len is 3 but the index is 3
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The message is very precise: the list has 3 items, so the valid positions are 0, 1 and 2, and we asked for position 3. This "off by one" mistake is the most common bug in all of programming, and Rust catches it the moment it happens.

Avoiding panics

Every common cause has a safe alternative that hands you an Option or a Result instead:

fn main() {
    let marks = vec![70, 85, 92];
    match marks.get(3) {
        Some(m) => println!("Mark: {}", m),
        None => println!("There is no fourth mark."),
    }
    let a: i32 = 10;
    match a.checked_div(0) {
        Some(q) => println!("{}", q),
        None => println!("Cannot divide by zero."),
    }
}
Output
There is no fourth mark.
Cannot divide by zero.

Use get instead of square brackets when an index might be wrong, checked_div and its friends checked_add and checked_mul when numbers might misbehave, and match or unwrap_or instead of unwrap.

When a panic is the right answer

A panic is right when continuing would be worse than stopping: when the program's own assumptions are broken, not when a user made a typo. expect("config file must have a name") documents such an assumption, and if it is ever wrong you get a clear message pointing straight at it.

Practice exercises

  1. Run the out-of-range example, then fix it so it prints the last mark using marks.len() - 1.
  2. Write a program that panics with your own message, and find the line number in the output.
  3. Replace an unwrap() in one of your earlier programs with a match that prints a friendly message.