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 ChainError and implements a kind() method

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 T with a causing error

ErrorIter

An iterator over all error causes/sources

Traits

ChainErrorDown

Convenience trait to hide the ChainError<T> implementation internals

ChainErrorFrom

ChainErrorFrom<T> is similar to From<T>

IntoChainError

IntoChainError<T> is similar to Into<T>

ResultTrait

Convenience methods for Result<> to turn the error into a decorated ChainError

Type Definitions

ChainResult

convenience type alias