1Interfaces for working with Errors. 2 3# Error Handling In Rust 4 5The Rust language provides two complementary systems for constructing / 6representing, reporting, propagating, reacting to, and discarding errors. 7These responsibilities are collectively known as "error handling." The 8components of the first system, the panic runtime and interfaces, are most 9commonly used to represent bugs that have been detected in your program. The 10components of the second system, `Result`, the error traits, and user 11defined types, are used to represent anticipated runtime failure modes of 12your program. 13 14## The Panic Interfaces 15 16The following are the primary interfaces of the panic system and the 17responsibilities they cover: 18 19* [`panic!`] and [`panic_any`] (Constructing, Propagated automatically) 20* [`PanicInfo`] (Reporting) 21* [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting) 22* [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating) 23 24The following are the primary interfaces of the error system and the 25responsibilities they cover: 26 27* [`Result`] (Propagating, Reacting) 28* The [`Error`] trait (Reporting) 29* User defined types (Constructing / Representing) 30* [`match`] and [`downcast`] (Reacting) 31* The question mark operator ([`?`]) (Propagating) 32* The partially stable [`Try`] traits (Propagating, Constructing) 33* [`Termination`] (Reporting) 34 35## Converting Errors into Panics 36 37The panic and error systems are not entirely distinct. Often times errors 38that are anticipated runtime failures in an API might instead represent bugs 39to a caller. For these situations the standard library provides APIs for 40constructing panics with an `Error` as it's source. 41 42* [`Result::unwrap`] 43* [`Result::expect`] 44 45These functions are equivalent, they either return the inner value if the 46`Result` is `Ok` or panic if the `Result` is `Err` printing the inner error 47as the source. The only difference between them is that with `expect` you 48provide a panic error message to be printed alongside the source, whereas 49`unwrap` has a default message indicating only that you unwrapped an `Err`. 50 51Of the two, `expect` is generally preferred since its `msg` field allows you 52to convey your intent and assumptions which makes tracking down the source 53of a panic easier. `unwrap` on the other hand can still be a good fit in 54situations where you can trivially show that a piece of code will never 55panic, such as `"127.0.0.1".parse::<std::net::IpAddr>().unwrap()` or early 56prototyping. 57 58# Common Message Styles 59 60There are two common styles for how people word `expect` messages. Using 61the message to present information to users encountering a panic 62("expect as error message") or using the message to present information 63to developers debugging the panic ("expect as precondition"). 64 65In the former case the expect message is used to describe the error that 66has occurred which is considered a bug. Consider the following example: 67 68```should_panic 69// Read environment variable, panic if it is not present 70let path = std::env::var("IMPORTANT_PATH").unwrap(); 71``` 72 73In the "expect as error message" style we would use expect to describe 74that the environment variable was not set when it should have been: 75 76```should_panic 77let path = std::env::var("IMPORTANT_PATH") 78 .expect("env variable `IMPORTANT_PATH` is not set"); 79``` 80 81In the "expect as precondition" style, we would instead describe the 82reason we _expect_ the `Result` should be `Ok`. With this style we would 83prefer to write: 84 85```should_panic 86let path = std::env::var("IMPORTANT_PATH") 87 .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`"); 88``` 89 90The "expect as error message" style does not work as well with the 91default output of the std panic hooks, and often ends up repeating 92information that is already communicated by the source error being 93unwrapped: 94 95```text 96thread 'main' panicked at 'env variable `IMPORTANT_PATH` is not set: NotPresent', src/main.rs:4:6 97``` 98 99In this example we end up mentioning that an env variable is not set, 100followed by our source message that says the env is not present, the 101only additional information we're communicating is the name of the 102environment variable being checked. 103 104The "expect as precondition" style instead focuses on source code 105readability, making it easier to understand what must have gone wrong in 106situations where panics are being used to represent bugs exclusively. 107Also, by framing our expect in terms of what "SHOULD" have happened to 108prevent the source error, we end up introducing new information that is 109independent from our source error. 110 111```text 112thread 'main' panicked at 'env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`: NotPresent', src/main.rs:4:6 113``` 114 115In this example we are communicating not only the name of the 116environment variable that should have been set, but also an explanation 117for why it should have been set, and we let the source error display as 118a clear contradiction to our expectation. 119 120**Hint**: If you're having trouble remembering how to phrase 121expect-as-precondition style error messages remember to focus on the word 122"should" as in "env variable should be set by blah" or "the given binary 123should be available and executable by the current user". 124 125[`panic_any`]: ../../std/panic/fn.panic_any.html 126[`PanicInfo`]: crate::panic::PanicInfo 127[`catch_unwind`]: ../../std/panic/fn.catch_unwind.html 128[`resume_unwind`]: ../../std/panic/fn.resume_unwind.html 129[`downcast`]: crate::error::Error 130[`Termination`]: ../../std/process/trait.Termination.html 131[`Try`]: crate::ops::Try 132[panic hook]: ../../std/panic/fn.set_hook.html 133[`set_hook`]: ../../std/panic/fn.set_hook.html 134[`take_hook`]: ../../std/panic/fn.take_hook.html 135[panic-handler]: <https://doc.rust-lang.org/nomicon/panic-handler.html> 136[`match`]: ../../std/keyword.match.html 137[`?`]: ../../std/result/index.html#the-question-mark-operator- 138