Thanks to visit codestin.com
Credit goes to lib.rs

#error-handling #report

no-std error-stack

A context-aware error-handling library that supports arbitrary attached user data

13 releases

0.6.0 Aug 30, 2025
0.5.0 Jul 12, 2024
0.4.1 Sep 4, 2023
0.4.0 Aug 23, 2023
0.1.1 Jun 10, 2022

#57 in Rust patterns

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

107,077 downloads per month
Used in 161 crates (104 directly)

MIT/Apache

285KB
4K SLoC

crates.io libs.rs rust-version documentation license

Open issues / Discussions

error-stack

error-stack is a context-aware error-handling library that supports arbitrary attached user data.

Read our announcement post for the story behind its origins.

The library enables building a Report around an error as it propagates:

use core::{error::Error, fmt};

use error_stack::{Report, ResultExt};

#[derive(Debug)]
struct ParseExperimentError;

impl fmt::Display for ParseExperimentError {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.write_str("invalid experiment description")
    }
}

impl Error for ParseExperimentError {}

fn parse_experiment(description: &str) -> Result<(u64, u64), Report<ParseExperimentError>> {
    let value = description
        .parse::<u64>()
        .attach_with(|| format!("{description:?} could not be parsed as experiment"))
        .change_context(ParseExperimentError)?;

    Ok((value, 2 * value))
}

#[derive(Debug)]
struct ExperimentError;

impl fmt::Display for ExperimentError {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.write_str("experiment error: could not run experiment")
    }
}

impl Error for ExperimentError {}

fn start_experiments(
    experiment_ids: &[usize],
    experiment_descriptions: &[&str],
) -> Result<Vec<u64>, Report<ExperimentError>> {
    let experiments = experiment_ids
        .iter()
        .map(|exp_id| {
            let description = experiment_descriptions.get(*exp_id).ok_or_else(|| {
                Report::new(ExperimentError)
                    .attach(format!("experiment {exp_id} has no valid description"))
            })?;

            let experiment = parse_experiment(description)
                .attach(format!("experiment {exp_id} could not be parsed"))
                .change_context(ExperimentError)?;

            Ok(move || experiment.0 * experiment.1)
        })
        .collect::<Result<Vec<_>, Report<ExperimentError>>>()
        .attach("unable to set up experiments")?;

    Ok(experiments.iter().map(|experiment| experiment()).collect())
}

fn main() -> Result<(), Report<ExperimentError>> {
    let experiment_ids = &[0, 2];
    let experiment_descriptions = &["10", "20", "3o"];
    start_experiments(experiment_ids, experiment_descriptions)?;

    Ok(())
}

This will most likely result in an error and print

Error: experiment error: could not run experiment
├╴at examples/demo.rs:50:18
├╴unable to set up experiments
│
├─▶ invalid experiment description
│   ├╴at examples/demo.rs:20:10
│   ╰╴experiment 2 could not be parsed
│
╰─▶ invalid digit found in string
    ├╴at examples/demo.rs:19:10
    ├╴backtrace with 31 frames (1)
    ╰╴"3o" could not be parsed as experiment

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

backtrace no. 1
   0: std::backtrace_rs::backtrace::libunwind::trace
             at /rustc/f3623871cfa0763c95ebd6ceafaa6dc2e44ca68f/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1: std::backtrace_rs::backtrace::trace_unsynchronized
             at /rustc/f3623871cfa0763c95ebd6ceafaa6dc2e44ca68f/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2: std::backtrace::Backtrace::create
             at /rustc/f3623871cfa0763c95ebd6ceafaa6dc2e44ca68f/library/std/src/backtrace.rs:331:13
   3: core::ops::function::FnOnce::call_once
             at /rustc/f3623871cfa0763c95ebd6ceafaa6dc2e44ca68f/library/core/src/ops/function.rs:250:5
   4: core::bool::<impl bool>::then
             at /rustc/f3623871cfa0763c95ebd6ceafaa6dc2e44ca68f/library/core/src/bool.rs:60:24
   5: error_stack::report::Report<C>::from_frame
             at ./src/report.rs:286:25
   6: error_stack::report::Report<C>::new
             at ./src/report.rs:272:9
   7: error_stack::context::<impl core::convert::From<C< for error_stack::report::Report<C>>::from
             at ./src/context.rs:83:9
   8: <core::result::Result<T,C< as error_stack::result::ResultExt<::attach_with
             at ./src/result.rs:158:31
   9: demo::parse_experiment
             at demo.rs:17:17
  10: demo::start_experiments::{{closure}}
             at demo.rs:48:30
   (For this example: additional frames have been removed)

Usage

Please see the documentation.

For more examples of error-stack in use, please check out the examples folder.

Contributors

error-stack was created and is maintained by HASH. As an open-source project, we gratefully accept external contributions and have published a contributing guide that outlines the process. If you have questions, please create a GitHub discussion.

License

error-stack is available under either of the [Apache License, Version 2.0] or [MIT license] at your option. Please see the LICENSE file for more information.

Dependencies

~0–620KB
~11K SLoC