Rust groups errors into two major categories:
- recoverable errors
- unrecoverable error
Recoverable Errors
When it is recoverable error then problem will report to the user and and retry the operation. This errors handle with the type Result since exception is not available in rust.
Ex: File not found error
Unrecoverable Errors
Unrecoverable errors are always symptoms of bugs. This errors handle with the panic!
macro and it will stop execution.
Ex: trying to access a location beyond the end of an array.
Recoverable Errors with Result
Result enum is defined as having two variants, Ok and Err, as follows:
enum Result<T, E> { Ok(T), Err(E), }
This T and E mention in here Result<T, E>
are generic type parameters.
T represent the type of value that will be return in success case and E represent the type of value that will be return in error/failure case.
use std::fs::File; fn main() { let f:u32 = File::open("program.txt"); }
error[E0308]: mismatched types --> src/main.rs:4:18 | 4 | let f: u32 = File::open("hello.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^ expected u32, found enum `std::result::Result` | = note: expected type `u32` found type `std::result::Result<std::fs::File, std::io::Error>`
We can modify code as follows to handle error:
use std::fs::File; use std::io::Error; fn main() { let f = File::open("program.txt"); match f { Ok(_file) => println!("File opened successfully"), Err(e) => println!("Error opening file: {}", e), } }
Unrecoverable Errors with panic!
When the panic!
macro executes, your program will print a failure message, unwind and clean up the stack, and then quit.
unwind - Rust walks back up the stack and cleans up the data from each function it encounters.
abort - Ends the program without cleaning up. Memory that the program was using will then need to be cleaned up by the operating system.
if you are using abort
then need to do modification in Cargo.toml
as follows:
panic = 'abort'
fn main() { panic!("This is an unrecoverable error!"); }
Output:
Compiling testing v0.1.0 (C:\Users\Sanija Methsen\Desktop\Rust\my-projects\testing) Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.93s Running `target\debug\testing.exe` thread 'main' panicked at src\main.rs:2:5: This is an unrecoverable error! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: process didn't exit successfully: `target\debug\testing.exe` (exit code: 101) PS C:\Users\Sanija Methsen\Desktop\Rust\my-projects\testing>
Using a panic! Backtrace
A backtrace is a detailed report showing the sequence of function calls that occurred before the panic, which is extremely helpful for debugging.
- Enable full backtraces:
For Linux/Mac (Bash/Zsh): RUST_BACKTRACE=1 cargo run For Windows Command Prompt (CMD): set RUST_BACKTRACE=1 cargo run
Output
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s Running `target\debug\testing.exe` thread 'main' panicked at src\main.rs:2:5: This is an unrecoverable error! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: process didn't exit successfully: `target\debug\testing.exe` (exit code: 101)
- Enable full backtraces with more details:
For Linux/Mac (Bash/Zsh): RUST_BACKTRACE=full cargo run For Windows Command Prompt (CMD): set RUST_BACKTRACE=full cargo run
Output
Compiling testing v0.1.0 (C:\Users\Sanija Methsen\Desktop\Rust\my-projects\testing) Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.10s Running `target\debug\testing.exe` thread 'main' panicked at src\main.rs:2:5: This is an unrecoverable error! stack backtrace: 0: 0x7ff767896511 - std::backtrace_rs::backtrace::win64::trace at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\..\..\backtrace\src\backtrace\win64.rs:85 1: 0x7ff767896511 - std::backtrace_rs::backtrace::trace_unsynchronized at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\..\..\backtrace\src\backtrace\mod.rs:66 2: 0x7ff767896511 - std::sys::backtrace::_print_fmt at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\sys\backtrace.rs:66 3: 0x7ff767896511 - std::sys::backtrace::impl$0::print::impl$0::fmt at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\sys\backtrace.rs:39 4: 0x7ff7678a299a - core::fmt::rt::Argument::fmt at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\core\src\fmt\rt.rs:177 5: 0x7ff7678a299a - core::fmt::write at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\core\src\fmt\mod.rs:1449 6: 0x7ff7678948e7 - std::io::Write::write_fmt<std::sys::pal::windows::stdio::Stderr> at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\io\mod.rs:1890 7: 0x7ff767896355 - std::sys::backtrace::BacktraceLock::print at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\sys\backtrace.rs:42 8: 0x7ff767897892 - std::panicking::default_hook::closure$0 at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panicking.rs:298 9: 0x7ff767897683 - std::panicking::default_hook at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panicking.rs:325 10: 0x7ff76789837f - std::panicking::rust_panic_with_hook at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panicking.rs:831 11: 0x7ff7678981d2 - std::panicking::begin_panic_handler::closure$0 at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panicking.rs:697 12: 0x7ff767896c4f - std::sys::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::closure_env$0,never$> at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\sys\backtrace.rs:168 13: 0x7ff767897e0e - std::panicking::begin_panic_handler at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panicking.rs:695 14: 0x7ff7678a7551 - core::panicking::panic_fmt at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\core\src\panicking.rs:75 15: 0x7ff76789118b - testing::main at C:\Users\Sanija Methsen\Desktop\Rust\my-projects\testing\src\main.rs:2 16: 0x7ff76789106b - core::ops::function::FnOnce::call_once<void (*)(),tuple$<> > at C:\Users\Sanija Methsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:250 17: 0x7ff76789113e - core::hint::black_box at C:\Users\Sanija Methsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\hint.rs:477 18: 0x7ff76789113e - std::sys::backtrace::__rust_begin_short_backtrace<void (*)(),tuple$<> > at C:\Users\Sanija Methsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\backtrace.rs:152 19: 0x7ff767891121 - std::rt::lang_start::closure$0<tuple$<> > at C:\Users\Sanija Methsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\rt.rs:199 20: 0x7ff767892d5c - std::rt::lang_start_internal::closure$0 at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\rt.rs:168 21: 0x7ff767892d5c - std::panicking::try::do_call at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panicking.rs:587 22: 0x7ff767892d5c - std::panicking::try at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panicking.rs:550 23: 0x7ff767892d5c - std::panic::catch_unwind at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\panic.rs:358 24: 0x7ff767892d5c - std::rt::lang_start_internal at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library\std\src\rt.rs:164 25: 0x7ff76789110a - std::rt::lang_start<tuple$<> > at C:\Users\Sanija Methsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\rt.rs:198 26: 0x7ff7678911a9 - main 27: 0x7ff7678a5ec0 - invoke_main at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78 28: 0x7ff7678a5ec0 - __scrt_common_main_seh at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288 29: 0x7ffe69e0259d - BaseThreadInitThunk 30: 0x7ffe6b14af38 - RtlUserThreadStart error: process didn't exit successfully: `target\debug\testing.exe` (exit code: 101)
- Disable backtraces:
For Linux/Mac (Bash/Zsh): RUST_BACKTRACE=0 cargo run For Windows Command Prompt (CMD): set RUST_BACKTRACE=0 cargo run
Output
thread 'main' panicked at 'Test panic', src\main.rs:2:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Unwrap and expect
unwrap
will return the value inside the Ok. If the Result is the Err variant, unwrap will call the panic! macro for us.
let num = "42".parse::<i32>().unwrap(); // Panics on Err
Using expect
instead of unwrap
and providing good error messages can convey your intent and make tracking down the source of a panic easier.
let num = "42".parse::<i32>().expect("Parsing failed"); // Panics with custom message
Propagating Errors
Error propagation is a fundamental concept in Rust that allows errors to be passed up the call stack to be handled by calling functions. The ? operator is Rust's primary mechanism for error propagation:
use std::fs; use std::io; fn read_config() -> Result<String, io::Error> { let content = fs::read_to_string("config.toml")?; Ok(content) } fn main() -> Result<(), io::Error> { let config = read_config()?; println!("Config: {}", config); Ok(()) }
Helpful Crates
thiserror
: For defining library error types
anyhow
: For application error handling
snafu
: Alternative error handling with backtraces
miette
: Fancy diagnostic error reporting
Top comments (0)