← Back to Rust Course | Chapter 10: Error Handling | Lesson 6 of 6

Panic Basics

A panic is Rust's way of stopping everything immediately because something went seriously, unrecoverably wrong.

Triggering a Panic Explicitly

The panic! macro immediately stops normal program execution with the given message, used for situations that should truly never happen.

Example: Triggering a Panic Explicitly

markup
fn main() {
    let should_continue = true;
    if !should_continue {
        panic!("This should never happen");
    }
    println!("Program continued normally");
}

Panics from Built-in Operations

Several standard operations panic automatically on invalid input, such as indexing an array out of bounds. This example shows a safe check before it would happen.

Example: Panics from Built-in Operations

markup
fn main() {
    let numbers = [1, 2, 3];
    let index = 2;
    if index < numbers.len() {
        println!("Safe access: {}", numbers[index]);
    } else {
        println!("Index out of bounds, avoided panic");
    }
}

Panic vs Result

panic! is appropriate for programming bugs and truly unrecoverable states, while Result is appropriate for expected, recoverable failure conditions that callers should be able to handle.

Example: Panic vs Result

markup
fn safe_divide(a: i32, b: i32) -> Result<i32, &'static str> {
    if b == 0 {
        Err("division by zero is an expected, recoverable error")
    } else {
        Ok(a / b)
    }
}

fn main() {
    match safe_divide(10, 0) {
        Ok(v) => println!("{}", v),
        Err(e) => println!("Handled gracefully: {}", e),
    }
}

Catching Panics with catch_unwind

In rare cases, std::panic::catch_unwind can catch a panic and prevent it from crashing the whole program, though this is uncommon and not a substitute for proper Result-based error handling.

Example: Catching Panics with catch_unwind

markup
use std::panic;

fn main() {
    let result = panic::catch_unwind(|| {
        println!("About to panic inside catch_unwind");
        panic!("controlled panic");
    });
    match result {
        Ok(_) => println!("No panic occurred"),
        Err(_) => println!("Panic was caught and handled"),
    }
}
Common Mistakes
  1. Using panic! for ordinary, expected error conditions instead of returning a Result that callers can handle gracefully.
  2. Assuming a panic can always be caught and recovered from like an exception -- by default it unwinds and terminates the current thread's work.
  3. Not realizing indexing out of bounds, integer overflow (in debug builds), and .unwrap() on None/Err all trigger a panic automatically.
Chapter Summary
  • panic!("message") immediately stops normal execution and begins unwinding (or aborting) the program.
  • Common built-in operations like out-of-bounds indexing or .unwrap() on None trigger a panic automatically.
  • Panics are meant for unrecoverable bugs, not for expected, everyday error conditions -- use Result for those.
  • RUST_BACKTRACE=1 can be set when running a program to print a full backtrace when a panic occurs.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.