Skip to main content

Crate oopsie

Crate oopsie 

Source
Expand description

Ergonomic, structured error handling for Rust.

oopsie centers on a single attribute macro:

#[oopsie] — generates context selectors, Display, Debug, and Error impls for your error type. Pass traced to also capture a backtrace and, with the tracing feature, a span-trace.

§Quick start

Define your error type:

#[oopsie::oopsie]
pub enum AppError {
    #[oopsie("Connection to {host} failed")]
    Connect { host: String, source: std::io::Error },

    #[oopsie("Key not found: {key}")]
    MissingKey { key: String },
}

Use it — bring the extension traits into scope with the prelude:

use oopsie::prelude::*;

fn connect(host: &str) -> Result<(), AppError> {
    std::net::TcpStream::connect(host)
        .context(app_oopsies::Connect { host })?;
    Ok(())
}

§Diagnostics

Pass traced to automatically capture a backtrace field and, with the tracing feature, a span-trace:

#[oopsie::oopsie(traced)]
pub enum AppError {
    #[oopsie("Connection to {host} failed")]
    Connect { host: String, source: std::io::Error },
}

traced also assigns each variant an automatic error code — module_path::Type::Variant — shown as Error[...] in Report headers. Override it per variant with #[oopsie(code = "...")], or disable it with #[oopsie::oopsie(traced, code = false)].

Call start_marker! early in a thread to hide the setup frames below it from rendered traces.

See the #[oopsie] documentation for the full parameter reference.

§Reporting

Report renders an error — message, source chain, span trace, backtrace — as a rich, colorized report. It implements Termination, so it can be returned straight from main. Report::run additionally installs the library’s panic hook for the duration of the closure, so panics are rendered in the same style:

use oopsie::Report;
use oopsie::prelude::*;

#[oopsie::oopsie(traced)]
pub enum AppError {
    #[oopsie("Key not found: {key}")]
    MissingKey { key: String },
}

fn run() -> Result<(), AppError> {
    let config: Option<&str> = Some("42");
    let _value = config.context(app_oopsies::MissingKey { key: "answer" })?;
    Ok(())
}

fn main() -> Report<AppError> {
    Report::run(run)
}

When run returns an error, the report is printed to stderr and the process exits with a failure code. To render panics outside of Report::run, install the hook process-wide with install_panic_hook once, early in main. Color output is auto-detected; override it with set_color_mode or per report via Report::no_colors / Report::force_colors.

(Requires the fancy feature.)

§Beyond typed errors

  • Welp is a string-shaped escape hatch for prototypes and one-off errors: Welp::new("..."), or .welp_context("...") on any Result via the prelude.
  • The oopsie::erased module converts any error into a serializable, type-erased representation — message, source chain, code/help, span trace, and backtrace — for transporting errors across process boundaries, e.g. API error responses. (Requires the serde feature.)

§What gets generated

For each variant or struct, #[oopsie] generates a context selector — a struct containing all the fields except the source error and any #[oopsie(capture)] fields.

Selectors for leaf variants (no source) expose .build() and .fail(), and work with Option::context. Selectors for variants with a source expose .build_error(source) via the Contextual trait. The methods are mutually exclusive — a source selector has no .build().

All selector fields accept Into<T>, so you can pass "str" for a String field.

.context(selector) on Result / Option builds the error for you — you only need to call these methods directly when constructing errors manually.

§Selector naming

The selector name is the variant name (for enums) or struct name (for structs), with a trailing "Error" suffix stripped.

Structs additionally get an "Oopsie" suffix by default — struct QueryError → selector QueryOopsie. Disable with #[oopsie(suffix(false))] or set a custom one with #[oopsie(suffix = "X")].

Variant / structSelector name
Connect (variant)Connect
ConnectionError (variant)Connection
QueryError (struct)QueryOopsie

§Module wrapping

Selectors can be placed in a generated module — the default for enums; structs default to no module. The auto-generated module name is derived from the error type name: strip trailing "Error", convert to snake_case, append _oopsies:

Error typeModule
AppErrorapp_oopsies
ConnErrorconn_oopsies
MyErrormy_oopsies

Control this with #[oopsie(module(false))] (disable) or #[oopsie(module(custom_name))].

An error type declared inside a function body requires #[oopsie(module(false))]: the generated module cannot reference items local to a function, so the wrapped selectors would be unable to name the error type.

§Display messages

Display strings follow format! semantics with named or positional interpolation:

  • #[oopsie("Failed to read {path}")] — named field
  • #[oopsie("Got {} errors", count)] — positional

If no display attribute is given, the variant or struct name is used verbatim as the message.

§Attribute reference

Each keyword has its own subsection below; the per-scope tables are a scannable index into them.

§Container (enum / struct)

KeywordEffect
moduleWrap selectors in a module
suffixSuffix on selector names
sizeCompile-time size assertion
pathPath to the oopsie crate
visSelector visibility
exit_codeDefault process exit code

The short form #[oopsie("msg")] on a container sets the struct’s display message (on enums the message goes on each variant instead).

Wraps the generated context selectors in a module, keeping them out of the surrounding namespace. Enabled by default for enums (auto-named by stripping a trailing Error, converting to snake_case, and appending _oopsies); disabled by default for structs.

Forms: module, module(true), module(false), module(name), module = "name".

An error type declared inside a function body needs module(false): the generated module cannot reference items local to a function, so wrapping the selectors in one leaves them unable to name the error type.

§Example

#[oopsie::oopsie]
#[oopsie(module(my_errors))]
pub enum AppError {
    #[oopsie("not found: {key}")]
    Missing { key: String },
}

fn main() {
    let err = my_errors::Missing { key: "k".to_owned() }.build();
    assert_eq!(err.to_string(), "not found: k");
}

Controls the suffix appended to generated selector names. Structs default to a "Oopsie" suffix (e.g. QueryError → selector QueryOopsie); enums default to no suffix. The selector base name is always the variant or struct name with a trailing Error stripped first.

Forms: suffix, suffix(true), suffix(false), suffix("X"), suffix = "X".

§Example

#[oopsie::oopsie]
#[oopsie(suffix("Ctx"))]
pub struct QueryError {
    query: String,
}

let err = QueryCtx { query: "SELECT 1".to_owned() }.build();
assert_eq!(err.to_string(), "QueryError");

Asserts the size of the error type at compile time, so an accidental growth of the error fails the build instead of silently bloating every Result that carries it. Accepts an exact size or a range, in bytes.

Forms: size(N), size(..=N), size(..N), size(N..), size(N..=M), size(N..M). Upper bounds may be inclusive (..=N, N..=M) or exclusive (..N, N..M). The unbounded size(..), the unsatisfiable size(..0), and any empty range (N..N, or N..M / N..=M whose low bound is not below / exceeds the high bound) are rejected.

Not available on a generic error type: its size depends on the type arguments and has no single value to assert, so combining size(...) with generic parameters is rejected.

§Example

#[oopsie::oopsie]
#[oopsie(size(..=64))]
pub enum AppError {
    #[oopsie("not found: {key}")]
    Missing { key: String },
}

§Project-wide default

With the settings feature, max-size = N under [package.metadata.oopsie] in the crate’s Cargo.toml caps every error derived in that crate, as if each carried #[oopsie(size(..=N))]. The same key is also honored from [workspace.metadata.oopsie] at the workspace root, applying to every member crate that opts into the settings feature. A per-type size(...) always overrides it, and max-size = 0 is rejected (remove the key to disable the cap). Overrides the path to the oopsie crate used in the generated code. Needed when oopsie is re-exported under a different path or renamed in Cargo.toml. Defaults to ::oopsie.

Forms: path = "some::path", path = some::path.

§Example

// A real custom path must name a crate that actually re-exports `oopsie`,
// which can't exist inside this crate's own doctest.
#[oopsie::oopsie]
#[oopsie(path = "my_crate::reexports::oopsie")]
pub enum AppError {
    #[oopsie("boom")]
    Boom,
}

Overrides the visibility of the generated selectors (and their module, if any). Defaults to the error type’s own visibility. A variant-level vis(...) overrides this for that one variant’s selector.

Forms: vis(pub), vis(pub(crate)), vis = "pub(crate)".

§Example

#[oopsie::oopsie]
#[oopsie(module(errs), vis(pub(crate)))]
pub enum AppError {
    #[oopsie("not found: {key}")]
    Missing { key: String },
}

fn main() {
    let err = errs::Missing { key: "k".to_owned() }.build();
    assert_eq!(err.to_string(), "not found: k");
}

Sets the default process exit code for the error type, surfaced via Diagnostic::oopsie_exit_code and used by Report’s Termination impl when the error is returned from main. Accepts an integer literal in 1..=255 (0 is rejected: it denotes success, contradictory on an error path).

On an enum it applies to every variant that does not set its own exit_code; on a struct it is the struct’s exit code.

Forms: exit_code = N.

§Example

use oopsie::Diagnostic as _;

#[oopsie::oopsie]
#[oopsie(module(false), exit_code = 70)]
pub struct AppError {
    detail: String,
}

let err = AppOopsie { detail: String::from("boom") }.build();
assert_eq!(err.oopsie_exit_code().map(|n| n.get()), Some(70));

§Variant / struct

KeywordEffect
displayDisplay message
transparentDelegate to the wrapped error
helpStatic help text
codeError code
exit_codeProcess exit code
provideProvide a typed value
visSelector visibility

The short form #[oopsie("msg {field}")] is shorthand for display(...). With the unstable feature, help and code are additionally surfaced through the nightly Provider API.

Sets the variant’s (or struct’s) Display message using format! semantics, with named ({field}) or positional ({}) interpolation over the item’s fields. This is the long form of the short #[oopsie("msg")]; use it when combining display with other keywords in the same attribute. Without any display, the variant or struct name is used verbatim.

Forms: display = "...", display("..."), display("... {}", expr).

§Example

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie(display("{count} items missing from {place}"))]
    Missing { count: u32, place: String },
}

let err = Missing { count: 3u32, place: "cache".to_owned() }.build();
assert_eq!(err.to_string(), "3 items missing from cache");

Delegates Display and the error source to the wrapped error, and generates a From<Inner> impl instead of a context selector — so the inner error converts directly with ?. A transparent variant or struct must have exactly one field: the source.

Forms: transparent, transparent = true, transparent = false.

§Example

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie(transparent)]
    Io { source: std::io::Error },
}

fn read() -> Result<(), AppError> {
    let _ = std::fs::read("/no/such/file")?;
    Ok(())
}

let err = read().unwrap_err();
assert!(matches!(err, AppError::Io { .. }));

Attaches static help text to the variant or struct, surfaced via Diagnostic::oopsie_help_text and shown by Report. The text follows format! semantics, so it can interpolate the item’s fields. For help derived from a field’s runtime Display, use the field-level #[oopsie(help)] instead.

Forms: help = "...", help("..."), help("... {}", expr).

§Example

use oopsie::Diagnostic as _;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie(display("config missing"), help = "run `app init` to create one")]
    NoConfig,
}

let err = NoConfig.build();
assert_eq!(err.oopsie_help_text().as_deref(), Some("run `app init` to create one"));

Attaches an error code to the variant or struct, surfaced via Diagnostic::oopsie_error_code and shown by Report. The code follows format! semantics, so it can interpolate the item’s fields. On a traced type it replaces the auto-generated code for this item.

Forms: code = "...", code("..."), code("... {}", expr).

§Example

use oopsie::Diagnostic as _;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie(display("bad request: {status}"), code("E{}", status))]
    Http { status: u16 },
}

let err = Http { status: 404u16 }.build();
assert_eq!(err.oopsie_error_code().as_deref(), Some("E404"));

Sets the process exit code for this variant, surfaced via Diagnostic::oopsie_exit_code and used by Report’s Termination impl when the error is returned from main. Accepts an integer literal in 1..=255 (0 is rejected: it denotes success, contradictory on an error path). A container-level exit_code is the default for every variant; a variant’s own value overrides it.

Forms: exit_code = N.

§Example

use oopsie::Diagnostic as _;

#[oopsie::oopsie]
#[oopsie(module(false), exit_code = 1)]
pub enum AppError {
    #[oopsie("bad usage")]
    Usage,
    #[oopsie("config error: {path}")]
    #[oopsie(exit_code = 78)]
    Config { path: String },
}

assert_eq!(Usage.build().oopsie_exit_code().map(|n| n.get()), Some(1));
assert_eq!(
    Config { path: String::from("x") }.build().oopsie_exit_code().map(|n| n.get()),
    Some(78)
);

Provides a value or reference for the variant or struct through the std::error::Request provider API (active with the unstable feature), letting callers retrieve typed data with Error::request_ref/request_value. The expression is evaluated against the item’s fields; ref provides a borrow.

Forms: provide(Type => expr), provide(ref, Type => expr).

§Example

use oopsie::ErrorCode;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie(display("query failed"))]
    #[oopsie(provide(ErrorCode => ErrorCode::from_static("E_QUERY")))]
    Query,
}

let err = Query.build();
assert_eq!(err.to_string(), "query failed");

Overrides the visibility of this one variant’s selector, taking precedence over any container-level vis(...). Useful for exposing a single selector from an otherwise crate-private error.

Forms: vis(pub), vis(pub(crate)), vis = "pub(crate)".

§Example

#[oopsie::oopsie]
#[oopsie(module(errs))]
enum AppError {
    #[oopsie("not found: {key}")]
    #[oopsie(vis(pub(crate)))]
    Missing { key: String },
}

fn main() {
    let err = errs::Missing { key: "k".to_owned() }.build();
    assert_eq!(err.to_string(), "not found: k");
}

§Field

KeywordEffect
fromMark the chained source error
captureAuto-fill via Capturable
provideProvide a typed value
backtraceCaptured backtrace field
spantraceCaptured span-trace field
tracesPacked (Backtrace, SpanTrace) field
locationCaptured caller location
helpDynamic help from this field’s Display
forwardForward source’s traces instead of capturing new ones

A field named source is auto-detected as the chained source error, and a Box<T> source is auto-unboxed so the selector accepts T (trait objects exempt).

Marks this field as the chained source error, supplied to the selector at construction (via .build_error(source) or .context(...)) rather than being a selector field. A field named source is detected automatically; use from to mark a differently-named field. from(false) opts a source-named field out. from(Type, transform) accepts a Type and stores transform(value); a Box<T> source is auto-unboxed so the selector takes T directly.

Forms: from, from(true), from(false), from(Type, transform).

§Example

use oopsie::Contextual as _;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("read failed")]
    Read {
        #[oopsie(from)]
        cause: std::io::Error,
    },
}

let err = Read.build_error(std::io::Error::other("disk"));
assert_eq!(err.to_string(), "read failed");

Auto-fills this field via the Capturable trait when the error is constructed, so it is excluded from the context selector instead of being caller-supplied. Trace-typed fields (Backtrace, SpanTrace, packed traces) get this automatically; capture(false) opts such a field back onto the selector.

Forms: capture, capture = true, capture = false, capture(true), capture(false).

§Example

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("request {id} failed")]
    Failed {
        id: u32,
        #[oopsie(capture)]
        at: std::time::SystemTime,
    },
}

// `at` is captured automatically, so the selector only takes `id`.
let err = Failed { id: 7u32 }.build();
assert_eq!(err.to_string(), "request 7 failed");

Provides a value or reference derived from this field through the std::error::Request provider API (active with the unstable feature), letting callers retrieve typed data with Error::request_ref/request_value. The expression names the field; ref provides a borrow of it.

Forms: provide(Type => expr), provide(ref, Type => expr).

§Example

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("lookup failed: {key}")]
    Lookup {
        #[oopsie(provide(ref, str => key.as_str()))]
        key: String,
    },
}

let err = Lookup { key: "missing".to_owned() }.build();
assert_eq!(err.to_string(), "lookup failed: missing");

Marks this field as the captured backtrace, surfaced via Diagnostic::oopsie_backtrace. The field’s type must have Backtrace as its last path segment; it is auto-captured (and excluded from the selector). Marking a field is only needed when its type isn’t recognized automatically.

Forms: backtrace, backtrace = true, backtrace = false.

§Example

use oopsie::Backtrace;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("boom")]
    Boom {
        #[oopsie(backtrace)]
        bt: Backtrace,
    },
}

let err = Boom.build();
assert_eq!(err.to_string(), "boom");

Marks this field as the captured span trace, surfaced via Diagnostic::oopsie_spantrace. The field’s type must have SpanTrace as its last path segment; it is auto-captured (and excluded from the selector). Marking a field is only needed when its type isn’t recognized automatically.

Forms: spantrace, spantrace = true, spantrace = false.

§Example

use oopsie::SpanTrace;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("boom")]
    Boom {
        #[oopsie(spantrace)]
        st: SpanTrace,
    },
}

let err = Boom.build();
assert_eq!(err.to_string(), "boom");

Marks this field as the packed (Backtrace, SpanTrace) pair, surfacing both through Diagnostic::oopsie_backtrace and oopsie_spantrace from one field. The type must be (Backtrace, SpanTrace) (optionally boxed); it is auto-captured and excluded from the selector. A packed traces field cannot coexist with separate backtrace/spantrace fields.

Forms: traces, traces = true, traces = false.

§Example

use oopsie::{Backtrace, SpanTrace};

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("boom")]
    Boom {
        #[oopsie(traces)]
        traces: (Backtrace, SpanTrace),
    },
}

let err = Boom.build();
assert_eq!(err.to_string(), "boom");

Marks this field as the captured caller location, surfaced via Diagnostic::oopsie_location. The field’s type must be &'static Location<'static> (the standard std::panic::Location); it is auto-captured (and excluded from the selector). Marking a field is only needed when its type isn’t recognized automatically.

Forms: location, location = true, location = false.

§Example

use std::panic::Location;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("boom")]
    Boom {
        #[oopsie(location)]
        at: &'static Location<'static>,
    },
}

let err = Boom.build();
assert_eq!(err.to_string(), "boom");

Uses this field’s runtime Display output as the error’s dynamic help text, surfaced via Diagnostic::oopsie_help_text. Unlike the variant-level help = "...", the text comes from the field value at runtime rather than a fixed string. At most one help field per variant or struct.

Forms: help, help = true, help = false.

§Example

use oopsie::Diagnostic as _;

#[oopsie::oopsie]
#[oopsie(module(false))]
pub enum AppError {
    #[oopsie("config invalid")]
    BadConfig {
        #[oopsie(help)]
        hint: String,
    },
}

let err = BadConfig { hint: "set PORT in .env".to_owned() }.build();
assert_eq!(err.oopsie_help_text().as_deref(), Some("set PORT in .env"));

On a source field, opt in to forwarding diagnostic traces from that source through this error type’s Diagnostic impl. backtrace and spantrace are forwarded by default; location is opt-in. A forwarded trace is read from the source rather than captured here, so the wrapping type stores no trace of its own for it — keeping nested errors small.

location is opt-in because the origin-most caller location is already captured at construction, so this layer’s own location field holds the leaf’s site; forwarding it instead reads the source’s stored location.

If the source does not implement Diagnostic (e.g. std::io::Error), the forwarded accessors return None — the wrapper keeps no trace and there is nothing to forward.

Forms: forward, forward = true, forward = false, forward(true), forward(false), forward(backtrace = …, spantrace = …, location = …).

§Example

use oopsie::{Contextual as _, Diagnostic as _};

#[oopsie::oopsie(traced)]
#[oopsie(module(false))]
pub enum LeafError {
    #[oopsie("leaf error")]
    Leaf,
}

#[oopsie::oopsie(traced)]
#[oopsie(module(false))]
pub enum WrapError {
    #[oopsie("wrap error")]
    Wrap {
        #[oopsie(forward)]
        source: LeafError,
    },
}

fn main() {
    let leaf = Leaf.build();
    let _: WrapError = Wrap.build_error(leaf);
}

§Generic error types

Type parameters, lifetimes, const parameters, bounds, and where clauses are supported on both enums and structs. A context selector carries only the parameters its captured fields reference: a field of type Vec<T> makes the selector generic over T, while a leaf variant that mentions no parameter stays non-generic and infers the destination’s parameters from the call site.

No bound is added beyond what you write. Interpolating a field in a display (or help/code) format string requires that field’s type to implement the formatting trait the placeholder uses, exactly as in any format! — if a type parameter is interpolated as {field} but is not Display, the error is the ordinary missing-Display bound at your format string. Add the bound yourself (T: Display) when the message needs it.

#[derive(Debug, Oopsie)]
#[oopsie(module(false))]
enum Lookup<K: std::fmt::Debug> {
    #[oopsie("no entry for {key:?}")]
    Missing { key: K },
}

let err: Lookup<u32> = Missing { key: 7 }.build();
assert_eq!(err.to_string(), "no entry for 7");

§Feature flags

FeatureDefaultToolchainEffect
fancyyesstableReport, colorized output, and the panic hook
tracingnostablespan-trace capture and the tracing-subscriber error layer
serdenostablethe erased module: serialize any error as a type-erased value
chrononostablechrono::DateTime<Local> timestamps for traced(timestamp(chrono = true))
jiffnostablejiff::Timestamp / jiff::Zoned timestamp capture
extrasnostablethe extras module: environment-snapshot Capturable helpers
settingsnostableread project-wide defaults from [package.metadata.oopsie]
unstablenonightlyumbrella for the two unstable features below
unstable-error-generic-member-accessnonightlytrace and diagnostic surfacing through the Provider API
unstable-try-trait-v2nonightly? converts a failed Result directly into a Report

§no_std

std is on by default; build with default-features = false for no_std + alloc targets (the crate always needs an allocator — bring your own with extern crate alloc and a global allocator in the consumer). fancy enables std (colorized Report rendering needs it), so it is unavailable on no_std targets. Panic hooks, backtraces, tracing, and clock-based timestamps (chrono / jiff) are also std-only; everything else — the derive, Welp, error chains, and Diagnostic/Display rendering — works unchanged.

§Project-wide settings

With the settings feature, a [package.metadata.oopsie] table in a crate’s Cargo.toml sets a default for every error derived in that crate. The same keys may also be declared once at the workspace root under [workspace.metadata.oopsie], so a multi-crate workspace can share a single set of defaults. Settings are read from each crate’s own manifest, never its dependencies’.

keyper-type equivalenteffect
max-size = 64size(..=64)cap on the error type’s size, in bytes
default-suffix = "Ctx"suffix("Ctx")suffix on generated selector names
default-suffix = falsesuffix(false)no selector suffix
default-vis = "pub(crate)"vis(pub(crate))visibility of selectors and their module
module = truemodulewrap selectors in a module
module = falsemodule(false)leave selectors at the crate top level
module = { suffix = "errors" }(none)name the module <type>_errors
traced = truetracedtrace by default
traced = { location = false }traced(location = false)tune a traced(...) sub-toggle

module and traced each take a bool or a table:

[package.metadata.oopsie.module]
enabled = true
suffix = "errors"

[package.metadata.oopsie.traced]
enabled = true
location = true
timestamp = false
packed = true
boxed = true
code = true

§Precedence

Each knob resolves independently, in this order (first set value wins):

  1. A per-type #[oopsie(...)] attribute.
  2. The crate’s own [package.metadata.oopsie].
  3. [workspace.metadata.oopsie] at the workspace root.
  4. The hardcoded default.

Setting one key in [package.metadata.oopsie] does not discard the remaining keys inherited from the workspace — each knob is resolved on its own. A crate that the workspace excludes does not inherit workspace settings.

When max-size is exceeded, the error names its source — either [package.metadata.oopsie] max-size or [workspace.metadata.oopsie] max-size — so the right table is clear.

§Notes

  • traced only affects types using the #[oopsie] attribute; a bare #[derive(Oopsie)] is never traced. enabled is the trace-by-default switch; the other keys set defaults applied whenever a type is traced.
  • default-suffix (the selector suffix) and module.suffix (the module name) are independent; module.suffix has no per-type form — a per-type module(name) sets the module’s full name instead.
  • timestamp = true records a SystemTime; the chrono / provide forms stay per-type (traced(timestamp(chrono = true))).

max-size rejects 0 and default-suffix = true is rejected as ambiguous (use a name or false); module.suffix / default-suffix must be valid identifier fragments and default-vis a valid visibility, else the build fails with a clear message.

Modules§

backtrace
Thread-local control over backtrace capture.
erased
Serializable, type-erased representations of errors.
extras
Ready-made Capturable types for ambient process and environment state.
prelude
Common imports for error handling at the call site.
trace_printer
Unified colored trace rendering for backtraces and span traces.
tracing
tracing integration helpers. tracing integration helpers.

Macros§

start_marker
Marks the start of meaningful backtraces on the current thread: frames below this call are hidden from rendered error and panic traces. The function containing the call stays visible. A later call replaces the marker; other threads are unaffected. RUST_BACKTRACE=full renders traces unfiltered, ignoring markers. Hiding is applied by the fancy feature’s renderers; without that feature the marker is recorded but has no effect.

Structs§

Backtrace
A captured stack backtrace with deferred symbol resolution.
Chain
An iterator over an error and its chain of source causes.
ErrorCode
An opaque error code, used for programmatic handling and matching.
HelpText
User-facing help text, intended to be shown in diagnostics.
NoSource
The stand-in “source” a leaf selector (one with no source field) builds from. Option::context uses it as the source when there is no error value to attach. You normally reach a leaf error through .build() / .fail() / Option::context, so you rarely name this directly.
OptionalSpanTrace
A wrapper around Option<SpanTrace> that implements Capturable.
Report
A wrapper around an error that provides rich, colorized output.
SpanTrace
A wrapper around tracing_error::SpanTrace.
Style
An opaque text style (foreground color plus modifiers) used by report themes.
Theme
A color theme: nine named colors plus the role accessors that paint a report from them. Small and Copy.
Welp
A string-shaped error type for prototypes, one-off errors, and quick string contexts.

Enums§

ColorMode
Color output configuration.
RustBacktrace
Whether backtrace capture is enabled, and how verbosely it should render.
SpanTraceStatus
The status of a SpanTrace: whether it was captured, or why it is empty.

Traits§

AsErrorSource
Normalize any source-error value to a &(dyn Error + 'static).
Capturable
A value that fills itself in when an error is constructed.
Contextual
Builds a target error from a context selector and a source error of type E.
Diagnostic
Trait for errors that expose diagnostic data.
ErrorChainExt
Walk an error and its source chain.
OptionExt
Extension trait on Option for converting None into a typed error.
ResultExt
Extension trait on Result for ergonomic error context wrapping.
WelpOptionExt
Extension trait on Option for converting None into a Welp.
WelpResultExt
Extension trait on Result for attaching a string message that produces a Welp.

Functions§

get_color_mode
Get the current global color mode.
get_theme
The current process-global theme.
install_panic_hook
Install a process-global panic hook that renders panics with a colored message, span trace, and backtrace via TracePrinter.
set_color_mode
Set the global color mode for all Report instances using Auto.
set_theme
Replace the process-global theme used by Report and the panic hook. Affects every report that doesn’t carry a per-instance override.

Attribute Macros§

oopsie
Attribute macro — the primary way to define an oopsie error type.

Derive Macros§

Oopsie
Derive macro that generates context selectors, Display, and Error impls for a struct or enum.