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
Welpis a string-shaped escape hatch for prototypes and one-off errors:Welp::new("..."), or.welp_context("...")on anyResultvia the prelude.- The
oopsie::erasedmodule 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 theserdefeature.)
§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 / struct | Selector 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 type | Module |
|---|---|
AppError | app_oopsies |
ConnError | conn_oopsies |
MyError | my_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)
| Keyword | Effect |
|---|---|
module | Wrap selectors in a module |
suffix | Suffix on selector names |
size | Compile-time size assertion |
path | Path to the oopsie crate |
vis | Selector visibility |
exit_code | Default 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
| Keyword | Effect |
|---|---|
display | Display message |
transparent | Delegate to the wrapped error |
help | Static help text |
code | Error code |
exit_code | Process exit code |
provide | Provide a typed value |
vis | Selector 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
| Keyword | Effect |
|---|---|
from | Mark the chained source error |
capture | Auto-fill via Capturable |
provide | Provide a typed value |
backtrace | Captured backtrace field |
spantrace | Captured span-trace field |
traces | Packed (Backtrace, SpanTrace) field |
location | Captured caller location |
help | Dynamic help from this field’s Display |
forward | Forward 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
| Feature | Default | Toolchain | Effect |
|---|---|---|---|
fancy | yes | stable | Report, colorized output, and the panic hook |
tracing | no | stable | span-trace capture and the tracing-subscriber error layer |
serde | no | stable | the erased module: serialize any error as a type-erased value |
chrono | no | stable | chrono::DateTime<Local> timestamps for traced(timestamp(chrono = true)) |
jiff | no | stable | jiff::Timestamp / jiff::Zoned timestamp capture |
extras | no | stable | the extras module: environment-snapshot Capturable helpers |
settings | no | stable | read project-wide defaults from [package.metadata.oopsie] |
unstable | no | nightly | umbrella for the two unstable features below |
unstable-error-generic-member-access | no | nightly | trace and diagnostic surfacing through the Provider API |
unstable-try-trait-v2 | no | nightly | ? 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’.
| key | per-type equivalent | effect |
|---|---|---|
max-size = 64 | size(..=64) | cap on the error type’s size, in bytes |
default-suffix = "Ctx" | suffix("Ctx") | suffix on generated selector names |
default-suffix = false | suffix(false) | no selector suffix |
default-vis = "pub(crate)" | vis(pub(crate)) | visibility of selectors and their module |
module = true | module | wrap selectors in a module |
module = false | module(false) | leave selectors at the crate top level |
module = { suffix = "errors" } | (none) | name the module <type>_errors |
traced = true | traced | trace 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):
- A per-type
#[oopsie(...)]attribute. - The crate’s own
[package.metadata.oopsie]. [workspace.metadata.oopsie]at the workspace root.- 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
tracedonly affects types using the#[oopsie]attribute; a bare#[derive(Oopsie)]is never traced.enabledis the trace-by-default switch; the other keys set defaults applied whenever a type is traced.default-suffix(the selector suffix) andmodule.suffix(the module name) are independent;module.suffixhas no per-type form — a per-typemodule(name)sets the module’s full name instead.timestamp = truerecords aSystemTime; thechrono/provideforms 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
Capturabletypes 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
tracingintegration helpers.tracingintegration 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=fullrenders traces unfiltered, ignoring markers. Hiding is applied by thefancyfeature’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
sourcecauses. - Error
Code - An opaque error code, used for programmatic handling and matching.
- Help
Text - User-facing help text, intended to be shown in diagnostics.
- NoSource
- The stand-in “source” a leaf selector (one with no
sourcefield) builds from.Option::contextuses 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. - Optional
Span Trace - A wrapper around
Option<SpanTrace>that implementsCapturable. - Report
- A wrapper around an error that provides rich, colorized output.
- Span
Trace - 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§
- Color
Mode - Color output configuration.
- Rust
Backtrace - Whether backtrace capture is enabled, and how verbosely it should render.
- Span
Trace Status - The status of a
SpanTrace: whether it was captured, or why it is empty.
Traits§
- AsError
Source - 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.
- Error
Chain Ext - Walk an error and its
sourcechain. - Option
Ext - Extension trait on
Optionfor convertingNoneinto a typed error. - Result
Ext - Extension trait on
Resultfor ergonomic error context wrapping. - Welp
Option Ext - Extension trait on
Optionfor convertingNoneinto aWelp. - Welp
Result Ext - Extension trait on
Resultfor attaching a string message that produces aWelp.
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
Reportinstances usingAuto. - set_
theme - Replace the process-global theme used by
Reportand 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
oopsieerror type.
Derive Macros§
- Oopsie
- Derive macro that generates context selectors,
Display, andErrorimpls for a struct or enum.