Rust Backtraces
A backtrace is a list of the function calls that were active when a panic happened. An environment variable switches the backtrace on.
The hint under every panic
A tiny program called steps panics in its last function. Run it plainly. The message comes with one polite note:
// in your terminal:
// $ ./stepsThe calls, listed
This is the steps program. Three small functions call each other, and the last one panics. With the variable set, the same run lists the calls under the message:
fn step_three() {
panic!("the third step failed");
}
fn step_two() {
step_three();
}
fn step_one() {
step_two();
}
fn main() {
step_one();
}full shows everything
The short trace on this program fills 12 lines. The full trace fills 64 lines. The extra lines are library and runtime frames:
// in your terminal:
// $ RUST_BACKTRACE=full ./stepsCapture a trace in code
Code can ask for a trace, too. capture() obeys the switch. With no variable set, its status reads Disabled:
let trace = std::backtrace::Backtrace::capture();
println!("{:?}", trace.status());No debug info, no names
Build the same file with debug info stripped. The trace shrinks to the frames it can still name:
// in your terminal:
// $ rustc -O -C debuginfo=0 steps.rs
// $ RUST_BACKTRACE=1 ./stepsExample
use std::backtrace::Backtrace;
fn main() {
let soft = Backtrace::capture();
println!("soft = {:?}", soft.status());
let forced = Backtrace::force_capture();
println!("forced = {:?}", forced.status());
}Key points
- Each frame stands for one call on the path to the panic.
- RUST_BACKTRACE is an environment variable.
- RUST_BACKTRACE is not a code setting.
- The same binary prints a trace or stays quiet, with no rebuild.
- Read a trace from the top.
- The top frame is where the program broke.
- Each frame below called the one above it.
- main sits near the bottom.
- RUST_BACKTRACE=1 prints a short trace.
- The short trace leaves some frames out and says so at the end.
- RUST_BACKTRACE=full prints every frame it can find.
- The runtime's own frames come along.
- Expect a long list.
- Rust reads every value except 0 as on.
- Even a typo like RUST_BACKTRACE=banana turns the short trace on.
- A panic message names only the line that failed.
In this example, main captures a trace twice. The first capture obeys the environment and reports Disabled, because no variable is set. The second capture forces the issue and reports Captured. Run the program with RUST_BACKTRACE=1 and the first line flips to Captured, too. Libraries use this trick to attach a trace to an error report.
Note
A trace needs debug info to name your functions.
Build with debug info stripped and the frames lose their names.
The calls still happened.
The labels are gone.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
Your backtrace shows main and none of your own function names. What is the likely cause?