Skip to main content

Crate errorstack

Crate errorstack 

Source
Expand description

A typed error system with error stacks and source-code location tracking.

The crate provides the ErrorStack trait, which extends std::error::Error with two methods: stack_source returning the next typed link in the error chain, and location returning the source-code location where the error was constructed.

The trait is mainly used via #[derive(ErrorStack)], which implements ErrorStack based on field names and attributes. The macro also generates helper constructors that automatically capture the call-site location, and when a source field is present return a closure allowing ergonomic chaining with Result::map_err.

An ErrorStack can be converted into a Report, which walks the full typed chain and produces a traceback with source-code locations.

§Motivation

Error::source only exposes causes as &dyn Error, so concrete types and any extra context they carry are lost. Backtraces show where code was running, not where errors were constructed. errorstack fills this gap by recording the source-code location of each error and preserving the full typed chain, so every cause and its origin are available for inspection or display.

§Quick start

use errorstack::{ErrorStack, Report};

#[derive(thiserror::Error, ErrorStack, Debug)]
pub enum AppError {
    #[error("io failed: {path}")]
    Io {
        path: String,
        source: std::io::Error,
        #[location]
        location: &'static std::panic::Location<'static>,
    },

    #[error("config failed")]
    Config {
        #[stack_source]
        source: ConfigError,
        #[location]
        location: &'static std::panic::Location<'static>,
    },
}

#[derive(thiserror::Error, ErrorStack, Debug)]
#[error("invalid config: {detail}")]
pub struct ConfigError {
    detail: String,
    #[location]
    location: &'static std::panic::Location<'static>,
}

fn load_config() -> Result<(), AppError> {
    let inner = ConfigError::new("missing field `port`".into());
    Err(AppError::config()(inner))
}

let err = load_config().unwrap_err();
let report = Report::new(&err);
assert_eq!(report.entries().count(), 2);

Printing report produces output similar to:

Error: config failed
      at src/main.rs:14:9

Caused by this error:
  1: invalid config: missing field `port`
        at src/main.rs:13:17

§Core concepts

§The ErrorStack trait

ErrorStack extends Error with two methods:

The trait is typically derived rather than implemented by hand. See the derive macro documentation for the full attribute reference, naming conventions, and generated constructor signatures.

§Report

Report collects an entire error chain into a list of Entry values, each pairing an error message with a source-code location where available.

Report provides a default Display implementation that renders the chain in a human-readable format with the outermost error first, followed by numbered causes and their locations. Callers that need a different structure (for example, emitting each frame as a structured telemetry event) can iterate over the Entry values directly via Report::entries.

§Compatibility with thiserror

errorstack uses the same field conventions as thiserror and is designed to pair with it.

Structs§

Entry
A single entry in an error report, pairing an error message with an optional source-code Location.
Report
A collected summary of an entire error chain, suitable for display or structured inspection.

Traits§

ErrorStack
An error within a typed error stack, preserving full error context as errors propagate up the call stack.

Derive Macros§

ErrorStack
Derive macro for ErrorStack.