Skip to content
Free public beta until December 4, 2026: every course is open, no card needed. After that, the first chapter of each course stays free and full access is a one-time $39 ($19 for up to 100 founding members chosen for helpful feedback). Your progress is kept. How the beta works

Recipe

Trace a panic to its cause

Use when: a program stopped with a message that says panicked at, and you need to find the bug

Goal: the line that panicked, the value that was wrong there, and the line that made that value

Taught in Panics

  1. 1

    The first line says panicked at, then a file, a line and a column. The number after the thread's name is a thread id. It changes every run, so ignore it.

    Example

    thread 'main' (63710710) panicked at src/main.rs:6:5: points at the file src/main.rs, line 6, column 5.

    Why: the place is where one of Rust's checks failed, so that's where to start.

  2. 2

    The next line says what went wrong. Match it to its kind.

    Example

    attempt to divide by zero on line 6 of average means that scores.len() was 0.

    • index out of bounds: the len is N but the index is N — an index equal to the length, often a count used as a position.
    • attempt to divide by zero — a divisor that was 0.
    • your own message from panic!, todo! or unreachable! — the code stopped on purpose, so read what it says.

    Why: the reason tells you which value to go looking for.

  3. 3

    Open the file at that line and find the value the reason names.

    Example

    Line 6 is total / scores.len() as u32. scores is a parameter, so the empty list came from a caller.

    • the bad value was made on this line — fix it here.
    • the bad value came in as a parameter — go on to Step 4 to find the caller.

    Why: the line that notices a problem is often not the line that caused it.

  4. 4

    Set the environment variable RUST_BACKTRACE to 1 and run the program again. The panic now prints a backtrace: the stack of calls at that moment.

    Example

    On macOS or Linux, run RUST_BACKTRACE=1 cargo run. In PowerShell, run $env:RUST_BACKTRACE = 1, then cargo run.

    Why: the plain message names one line; the backtrace names every call that led to it.

  5. 5

    Skip the frames that belong to Rust itself: names that start with core::, std:: or __rustc::. The first frame with your package's name is where the panic happened. Each frame below it is the caller of the one above. Read down until you reach the line that made the bad value.

    Example

    Frames 0 to 2 are Rust's. Frame 3, scores::average at line 6, is the panic. Frame 4, scores::report at line 10, passed the list on. Frame 5, scores::main at line 15, called report(&[]). The empty list on line 15 is the bug.

    Why: each caller handed a value down, so the cause sits at or below the frame that panicked.

Common mistakes

  • Fixing the line that panicked when the bad value came from a caller.
  • Reading the backtrace from the bottom up, or stopping at Rust's own frames at the top.
  • Taking the number after 'main' for a line number. It's a thread id.
  • Waiting for a backtrace without setting RUST_BACKTRACE. The plain message only suggests it.