Crate chainerror[−][src]
chainerror
provides an error backtrace without doing a real backtrace, so even after you strip
your
binaries, you still have the error backtrace.
Having nested function returning errors, the output doesn't tell where the error originates from.
use std::path::PathBuf; type BoxedError = Box<dyn std::error::Error + Send + Sync>; fn read_config_file(path: PathBuf) -> Result<(), BoxedError> { // do stuff, return other errors let _buf = std::fs::read_to_string(&path)?; // do stuff, return other errors Ok(()) } fn process_config_file() -> Result<(), BoxedError> { // do stuff, return other errors let _buf = read_config_file("foo.txt".into())?; // do stuff, return other errors Ok(()) } fn main() { if let Err(e) = process_config_file() { eprintln!("Error:\n{:?}", e); } }
This gives the output:
Error:
Os { code: 2, kind: NotFound, message: "No such file or directory" }
and you have no idea where it comes from.
With chainerror
, you can supply a context and get a nice error backtrace:
use chainerror::prelude::v1::*; use std::path::PathBuf; type BoxedError = Box<dyn std::error::Error + Send + Sync>; fn read_config_file(path: PathBuf) -> Result<(), BoxedError> { // do stuff, return other errors let _buf = std::fs::read_to_string(&path).context(format!("Reading file: {:?}", &path))?; // do stuff, return other errors Ok(()) } fn process_config_file() -> Result<(), BoxedError> { // do stuff, return other errors let _buf = read_config_file("foo.txt".into()).context("read the config file")?; // do stuff, return other errors Ok(()) } fn main() { if let Err(e) = process_config_file() { eprintln!("Error:\n{:?}", e); } }
with the output:
Error:
examples/simple.rs:14:51: read the config file
Caused by:
examples/simple.rs:7:47: Reading file: "foo.txt"
Caused by:
Os { code: 2, kind: NotFound, message: "No such file or directory" }
chainerror
uses .source()
of std::error::Error
along with #[track_caller]
and Location
to provide a nice debug error backtrace.
It encapsulates all types, which have Display + Debug
and can store the error cause internally.
Along with the ChainError<T>
struct, chainerror
comes with some useful helper macros to save a lot of typing.
chainerror
has no dependencies!
Debug information is worth it!
Features
display-cause
: turn on printing a backtrace of the errors in Display
Tutorial
Read the Tutorial
Modules
prelude | convenience prelude |
Macros
derive_err_kind | Derive an Error for an ErrorKind, which wraps a |
derive_str_context | Convenience macro to create a "new type" T(String) and implement Display + Debug for T |
Structs
ChainError | chains an inner error kind |
ErrorIter | An iterator over all error causes/sources |
Traits
ChainErrorDown | Convenience trait to hide the |
ChainErrorFrom |
|
IntoChainError |
|
ResultTrait | Convenience methods for |
Type Definitions
ChainResult | convenience type alias |