#[derive(ErrorStack)]
{
// Attributes available to this derive:
#[source]
#[stack_source]
#[location]
}
Expand description
Derive macro for ErrorStack.
Supports enums and structs with named fields. Note that the type must
also implement Display and
Error. This can be accomplished manually or via
thiserror.
This macro implements ErrorStack according to field names and
attributes, and generates an ergonomic constructor for each struct or
enum variant that captures caller location via #[track_caller] and
composes naturally with [Result::map_err] for error chaining.
§Attributes
The following field attributes are available:
| Attribute | Effect | Auto-detected |
|---|---|---|
#[source] | Marks a field as the error source. | when field is named source |
#[stack_source] | Marks the field as both the error source and an ErrorStack implementor, enabling typed chain walking via ErrorStack::stack_source. Implies #[source]. | no |
#[location] | Indicates the field stores a &'static Location<'static>, captured automatically at construction time. | no |
These attributes follow the same field conventions as
thiserror, allowing
both crates to be ergonomically used together.
§Stack sources
Any source field that implements ErrorStack should be annotated with
#[stack_source] to preserve the typed error chain. The macro cannot
inspect trait implementations, so without this annotation the source is
treated as a plain [std::error::Error] and chain walking stops at that
field.
§Optional sources
A source field may be wrapped in [Option] to represent errors that
do not always have an underlying cause. When the macro detects an
Option<T> source field, it generates two constructors instead of
one:
| Constructor | Signature | Source value |
|---|---|---|
variant_name / new | (user_fields…) -> Self | None |
variant_name_with / new_with | (user_fields…) -> impl FnOnce(T) -> Self | Some(source) |
§Error constructors
This macro also generates helper constructors for each struct or enum
variant. Every constructor is marked #[track_caller], so the
call-site location is recorded without manual boilerplate. When a
source field is present alongside user fields, the constructor returns
impl FnOnce(SourceTy) -> Self, capturing the user fields and
composing directly with [Result::map_err]. When the source is the
only field, the constructor takes it as a parameter and returns Self
directly.
Constructors are pub(crate) and named new for structs or
snake_cased_variant for enum variants. Remaining fields
become parameters, while #[source] and #[location] fields are filled
automatically.
§Examples
The macro may be derived on enums and structs with named fields. This
example shows both, with thiserror compatibility.
#[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("inner failed")]
Inner {
#[stack_source]
source: ConfigError,
#[location]
location: &'static std::panic::Location<'static>,
},
#[error("not found: {id}")]
NotFound {
id: String,
#[location]
location: &'static std::panic::Location<'static>,
},
}
#[derive(thiserror::Error, ErrorStack, Debug)]
#[error("config: {detail}")]
pub struct ConfigError {
detail: String,
#[location]
location: &'static std::panic::Location<'static>,
}The derive above generates the following constructors:
impl AppError {
// Source variants return a closure for use with map_err.
pub(crate) fn io(path: String) -> impl FnOnce(io::Error) -> Self;
pub(crate) fn inner(source: ConfigError) -> Self;
// Sourceless variants return Self directly.
pub(crate) fn not_found(id: String) -> Self;
}
impl ConfigError {
pub(crate) fn new(detail: String) -> Self;
}Source and location fields are handled automatically by these constructors, keeping call sites concise:
let _content = std::fs::read_to_string("Cargo.toml")
.map_err(AppError::io("Cargo.toml".into()))?;
let _err = AppError::not_found("abc".into());