n0-error
An Rust error library that supports tracking the call-site location of errors.
This crate provides a StackError trait and proc macro to ergonomically work with nested
enum and struct errors, while allowing to track the call-site location for the
full error chain.
It also has a AnyError type that works similar to anyhow errors while keeping
the location metadata of StackError errors accessible through the full error chain.
Example
use ;
/// The `stack_error` macro controls how to turn our enum into a `StackError`.
///
/// * `add_meta` adds a field to all variants to track the call-site error location
/// * `derive` adds `#[derive(StackError)]`
/// * `from_sources` creates `From` impls for the error sources
/// We can use the [`stack_error`] macro on structs as well.
/// The `Result` type defaults to `AnyError` for the error variant.
///
/// Errors types using the derive macro convert to `AnyError`, and we can add additional context
/// with the result extensions.
The error returned from process would look like this in the alternate display format:
failed to process input: invalid input: wanted 23 but got 13
and like this in the debug format with RUST_BACKTRACE=1 or RUST_ERROR_LOCATION=1:
failed to process input (examples/basic.rs:61:17)
Caused by:
invalid input (examples/basic.rs:36:5)
wanted 23 but got 13 (examples/basic.rs:48:13)
Details
- All errors using the macro implement the
StackErrortrait, which exposes call-site metadata for where the error occurred. Itssourcemethod returns references which may be other stack errors, allowing access to location data for the entire error chain. - The proc macro can add a
metafield to structs or enum variants. This field stores call-site metadata accessed through theStackErrortrait.- Call-site metadata in the
metafield is collected only ifRUST_BACKTRACE=1orRUST_ERROR_LOCATION=1env variable is set. Otherwise, it is disabled to avoid runtime overhead. - The declarative macro
e!provides an ergonomic way to construct such errors without explicitly setting the field. The crate'sensureandbailmacro also do this.
- Call-site metadata in the
- The crate includes an
AnyErrortype, similar toanyhow::Error. When created from aStackError, the call-site metadata is preserved.AnyErroris recommended for applications and tests, while libraries should use concrete derived errors.- All stack errors convert to
AnyError, so they can be propagated to such results with?. - For std errors, use
std_contextoranyerrto convert toAnyError. For stack errors, usecontextor simply propagate with?. - Result extension traits provide conversions between results with
StackErrors,std::error::Errors toAnyError, with support for attaching context.
- All stack errors convert to
- Both
AnyErrorand all errors using theStackErrorderive feature consistent, structured output that includes location metadata when available.
Feature flags
anyhow(off by default): EnablesFrom<anyhow::Error> for AnyErrorandimpl StackError for anyhow::Error
License
Copyright 2025 N0, INC.
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.