Skip to main content

Crate gix_error

Crate gix_error 

Source
Expand description

Common error types and utilities for error handling.

§Classification and recovery

Error classification matters because it lets a generic caller choose a recovery approach, supporting resilient software. Classes describe different remedies, not just different wording:

ClassRecovery approach
CancelledStop; preserve the caller’s intent instead of automatically retrying.
CorruptionRepair, replace, or re-fetch malformed data.
ResourceExhaustionReduce usage, adjust a limit, or free capacity.
ValidationCorrect the caller’s input.
UnsupportedSwitch implementation, capability, format, protocol, or strategy.
UnauthenticatedObtain or refresh credentials, distinct from authenticated-but-forbidden.
PermissionDeniedObtain authorization or change permissions.
ConflictRefresh or reconcile state before retrying against the new state.
NotFoundCreate the resource, use a fallback, or accept absence.
RetryableConsider a bounded retry, possibly after waiting.

The table follows Class’s suggested recovery precedence, highest first. Error::dominant_class() and Exn::dominant_class() return the highest-precedence class present, or None for unclassified errors. For borrowed errors, use classify() followed by dominant_class(). This uses the smallest Class under its ordering, rather than the first classification in traversal order.

A class guides recovery; it does not establish that recovery is safe. An operation whose outcome is unknown may already have performed side effects, so retrying can duplicate them even after a transient failure. Inspect concrete recovery errors and partial outcomes when necessary. Multiple causes can suggest different remedies; a matching class does not make sibling failures ignorable. Both retry policies reject explicit cancellation anywhere in the inspected causes; Error::is_retryable() only reports whether a retryable cause exists.

Leave errors unclassified when the remedy is unknown. An external program’s failed exit status alone does not establish a class. Preserve genuine callee errors rather than assigning their context an unsupported guess. Classify intrinsic conditions at their definition; use tag() for context-dependent classifications.

§Usage

Use Result and Error for public APIs with erased or message-based errors in plumbing crates and in gix. Public traits, callbacks, iterator items, associated errors, and re-exported APIs follow the same rule. It’s Ok to preserve concrete error types already exposed by public signatures, including ExnResult<T, Specific> and Exn<Specific>, if this helps readability and consumers. Native std::io::Result, standalone concrete-error results, and generic error adapters can retain their types.

Private and pub(crate) implementations also use Result for erased or message-based errors. Retain concrete errors when callers benefit from typed recovery or payload access. Use ExnResult<T, E> or ExnMessageResult<T> when callers need a specific exception type or manipulate exception trees.

The default helpers return Error and Result; their _typed variants retain an Exn<E>:

Use ResultExt::or_error() to convert native errors or exceptions to Result without adding context. Existing Error values pass through unchanged. Conversions preserve concrete recovery errors, causes, metadata, and caller locations; ?, .into(), and Exn::into_error() also convert exceptions to Error. Use Error::into_exn() to recover an exception tree for internal processing, including rearranging child frames.

§Caller locations

The error-print-location feature enables caller locations in diagnostics. Paths with conventional src, tests, examples, or benches directories are shortened to the containing package directory and source path; Cargo registry package versions are omitted. For example, /home/user/.cargo/registry/src/index.crates.io-hash/gix-url-0.39.0/src/parse.rs:349 is displayed as gix-url/src/parse.rs:349. Package-relative source paths are retained; paths whose package root cannot be inferred from these directory conventions fall back to the filename.

This only changes formatting: inspected locations retain the compiler-provided file, line, and column. A location contains no Cargo package metadata, so a directory that differs from the package name cannot be renamed automatically. Build owners can use rustc’s --remap-path-prefix to control captured paths for arbitrary source layouts. Alternate formatting continues to omit locations.

§Standard Error Types

Use these types for diagnostic context when recovery does not depend on a specific condition or structured payload. Otherwise retain a concrete Error-implementing type, and use it with ResultExt::or_raise(<StandardErrorType>) or OptionExt::ok_or_raise(<StandardErrorType>), or sibling methods.

All these types implement Error.

§Message and ClassificationMarker

Message combines a diagnostic message, an optional Class, and named scalar values. Use it for diagnostic context, or instead of a chain of type-bearing errors when those layers only describe a single failure. Keep concrete errors when callers need to match a particular condition, even without a payload. not_found(), validation(), corruption(), retryable(), resource_exhaustion(), allocation_limit(), allocation_failure(), cancelled(), permission_denied(), unauthenticated(), conflict(), and unsupported() construct classified messages. message() and Message::new() start without a class or values. Message::with_class() and Message::with() add them to the same diagnostic. Use message! for formatting, equivalent to Message::new(format!("…")) or format!("…").into(). Message::corrupted() and Message::validation() are shortcuts for Class::Corruption and Class::Validation, respectively: message!("invalid record at {offset}").corrupted() or message!("invalid count: {count}").validation(). The other classes have matching builders: Message::not_found(), Message::retryable(), Message::resource_exhaustion(), Message::allocation_limit(), Message::allocation_failure(), Message::cancelled(), Message::permission_denied(), Message::unauthenticated(), Message::conflict(), and Message::unsupported(). Message::corrupted_error(), Message::validation_error(), Message::not_found_error(), Message::retryable_error(), Message::resource_exhaustion_error(), Message::allocation_limit_error(), Message::allocation_failure_error(), Message::cancelled_error(), Message::permission_denied_error(), Message::unauthenticated_error(), Message::conflict_error(), and Message::unsupported_error() combine these builders with ErrorExt::raise() when an Error is needed directly. Prefer corruption() or validation() for static messages when more concise.

Classification does not determine which diagnostic values can be attached. For example, corruption("Malformed reference").with_input(bytes) preserves offending bytes in the same error that describes their corruption. No extra validation error is needed just to store input. Use explicit classified constructors or builders: converting a string to Message does not infer a class from the function’s return type.

TypeDiagnosticClassificationPurpose
MessageVisible message and optional valuesOptionalDescribe a failure without a custom error type
ClassificationMarkerTransparent, no diagnostic of its ownRequiredClassify an existing error while preserving its concrete type
use gix_error::{ErrorExt, Message, MetadataValue};

let error = gix_error::not_found("Reference does not exist")
    .with("path", std::path::Path::new("HEAD"))
    .raise();
assert!(error.is_not_found());
assert!(error.probable_cause().is::<Message>());
assert_eq!(error.metadata().next().expect("lookup details")["path"], MetadataValue::Path("HEAD".into()));

Callers should add context using information they already possess and document its keys on the function that returns it. Preserve real callee errors, especially concrete recovery signals and complex results discovered by the callee, such as partial outcomes:

use gix_error::{message, ResultExt, Message, MetadataValue};

let error = Err::<(), _>(std::io::Error::from(std::io::ErrorKind::NotFound))
    .or_raise(|| message("Could not read reference").with("path", std::path::Path::new("HEAD")))
    .expect_err("the lookup failed");
assert!(error.is_not_found());
assert!(error.probable_cause().is::<std::io::Error>());
let context = error.error().downcast_ref::<Message>().expect("message context");
assert_eq!(context.class, None, "the callee, not the context, supplies the classification");
let values = error.metadata().next().expect("lookup context");
assert_eq!(values["path"], MetadataValue::Path("HEAD".into()));

Exn::metadata() and Error::metadata() yield each message’s non-empty Metadata dictionary in error traversal order. Each dictionary maps names to MetadataValues. Keys are local to their context. Use Exn::metadata_merged() or Error::metadata_merged() to obtain one owned dictionary, with more specific causes overriding enclosing contexts. Merging independent causes discards their origin; later-visited values win. Metadata documents common schemas for input validation and external program runtime failures. These conventions do not require collecting additional information or imply a classification. To identify a specific failure without inspecting its values, see matching a specific failure.

§Exn<ErrorType> and Exn

The Exn type does not implement Error itself, but is able to store causing errors via ResultExt::or_raise_typed() (and sibling methods) as well as location information of the creation site.

Use exceptions in helpers whose callers need a typed context or tree operations such as Exn::chain_all(). Exn::erased and ExnResult<T> let these helpers combine different exception types. Other helpers use Result, which retains causes and locations without conversions at each caller. Preserve concrete public exception signatures.

Propagate existing Error values directly with ? when the callee already provides enough context. Use .or_raise(|| message("context information")) or its siblings when added context helps diagnose the failure, explains the operation’s purpose, or identifies user-controlled input such as configuration values. Keep such context even when failures are rare, then errors serve as in-code explanation and intent.

§Callback results

Public and private callbacks with erased or message-based errors use Result<T>; concrete callback errors retain their types. Add context with ResultExt::or_raise() when propagating a callback failure:

use gix_error::{message, Result, ResultExt};

fn parse_count(input: &str) -> Result<u64> {
    input.parse::<u64>().or_raise(|| message("could not parse count"))
}

pub fn process(callback: impl FnOnce() -> Result<u64>) -> Result<u64> {
    callback().or_raise(|| message("callback failed"))
}

assert_eq!(process(|| parse_count("42"))?, 42);

Private callbacks that need exception-tree operations may use ExnResult or ExnMessageResult. Use ResultExt::or_erased() only when such a callback requires an erased exception.

§Error — Exn with std::error::Error

Since Exn does not implement std::error::Error, it cannot be used where that trait is required (e.g. std::io::Error::other(), or as a #[source] in another error type). The Error type bridges this gap: it implements std::error::Error and converts from any Exn<E> via From, preserving the full error tree and location information.

ⓘ
// Convert an Exn to something usable as std::error::Error:
let exn: Exn<Message> = message("something failed").raise_typed();
let err: gix_error::Error = exn.into();
let err: gix_error::Error = exn.into_error();

// Useful where std::error::Error is required:
std::io::Error::other(exn.into_error())

It can also be created directly from any std::error::Error via Error::from_error(), which preserves native formatting for tree-backed errors. For native-error results, prefer ResultExt::or_error() to capture the caller location and use exception formatting. When a constructor is needed, invoke it in a closure, e.g. .map_err(|err| Error::from_boxed(err)). Passing the constructor directly to an adapter captures a FnOnce shim’s location instead of the call site.

§Tests with TestResult

Return TestResult from #[test] functions to propagate ordinary errors, Exn<E>, and Error directly with ?. It defaults to Result<(), TestError>; helpers returning a value can use TestResult<T>. Accepted errors must convert into Box<dyn std::error::Error + Send + Sync + 'static>.

When a test returns an error, Rust’s test harness prints TestError’s Debug output, including the complete diagnostic tree or chain. Captured caller locations are printed when the error-print-location feature is enabled; alternate formatting omits them.

use gix_error::{message, ResultExt, TestResult};

#[test]
fn parses_count() -> TestResult {
    let expected: usize = "42".parse()?;
    let actual = "42".parse::<usize>().or_raise(|| message("could not parse count"))?;
    assert_eq!(actual, expected, "context preserves the parsed count");
    Ok(())
}

§Migrating from thiserror

This section describes the mechanical translation from thiserror error enums to gix-error. In Cargo.toml, replace thiserror = "<version>" with gix-error = { version = "^0.1.0", path = "../gix-error" }.

§Choosing the replacement type

Use Result for diagnostic messages, including validation failures without callee errors, in public and private code. Message carries an optional class and named scalar values; Error retains the diagnostic context and causes. Keep a concrete error type in ExnResult when recovery requires a specific condition or structured payload. Public trait associated types also use Error for message-based errors, including bare Message errors. Preserve concrete public exception signatures. Internal results retain ExnMessageResult or ExnResult when callers need a specific exception type or exception-tree operations. Define at most one operation-specific error type, normally a public, #[non_exhaustive] enum named Error. Related methods should share it. Broad Class values categorize errors; variants define specific recovery decisions. Preserve genuine callee errors as causes instead of formatting them into text.

Use the chosen type directly in signatures, importing it under its canonical name where helpful. Crate-specific and operation-specific forwarding aliases or renamed error exports are unnecessary. Facades may re-export the canonical types, as gix does with Error, Exn, Result, ExnResult, and ExnMessageResult. Always import the result aliases directly and use their bare names in signatures.

§Translating variants

Translate variants to messages only when they provide diagnostics without a specific recovery contract. Use .raise() to wrap standalone errors into an Error, and ResultExt::or_raise() to preserve callee errors with additional context. For early returns, use bail! with a concrete error, message, or format arguments, such as bail!(Error::SomethingFailed), bail!(message("something went wrong")), or bail!("invalid input: {input}"). Prefer to import bail with use gix_error::bail; (or use gix::error::bail; in applications) and invoke it as bail!(...) instead of using a qualified path. String shorthand is unclassified unless a builder supplies a class. In plumbing APIs, classify known input or data failures explicitly, e.g. bail!(validation("invalid input")) or bail!("invalid record at {offset}".corrupted()). To add context when returning Result, use bail!(err.and_raise(message("context"))); reserve ErrorExt::and_raise_typed() for ExnResults that require an exception type. When passing an existing Exn, keep any context and explicit erasure inside the macro; propagating an existing public Error should use return Err(err).

Static message variant:

ⓘ
// BEFORE:
#[error("something went wrong")]
SomethingFailed,
// → Err(Error::SomethingFailed)

// AFTER (returning gix_error::Result):
// → Err(message("something went wrong").raise())

Formatted message variant:

ⓘ
// BEFORE:
#[error("unsupported format '{format:?}'")]
Unsupported { format: Format },
// → Err(Error::Unsupported { format })

// AFTER (returning gix_error::Result):
// → Err(message!("unsupported format '{format:?}'").raise())

#[from] / #[error(transparent)] variant without a recovery contract — delete the forwarding variant; at each call site, use ResultExt::or_raise() to add context:

ⓘ
// BEFORE:
#[error(transparent)]
Io(#[from] std::io::Error),
// → something_that_returns_io_error()?  // auto-converted via From

// AFTER (the variant is deleted):
// → something_that_returns_io_error()
//       .or_raise(|| message("context about what failed"))?

#[source] variant with diagnostic context only — use ResultExt::or_raise():

ⓘ
// BEFORE:
#[error("failed to parse config")]
Config(#[source] config::Error),
// → Err(Error::Config(err))

// AFTER:
// → config_call().or_raise(|| message("failed to parse config"))?

Guard / assertion — use ensure!:

ⓘ
// BEFORE:
if !condition {
    return Err(Error::SomethingFailed);
}

// AFTER (returning Exn<Message>, with a validation class):
ensure!(condition, gix_error::validation("something went wrong"));

// AFTER (returning Exn<Message>):
ensure!(condition, message("something went wrong"));

§Updating the function signature

When replacing a diagnostic-only error enum, change the return type and add the necessary imports:

ⓘ
// BEFORE:
fn parse(input: &str) -> Result<Value, Error> { ... }

// AFTER (public or private):
use gix_error::{message, ErrorExt, Result, ResultExt};
fn parse(input: &str) -> Result<Value> { ... }

Public APIs that already expose a concrete error, such as ExnResult<Value, SpecificError>, retain that type.

§Updating tests

Tests of diagnostic wording can use string assertions:

ⓘ
assert_eq!(result.expect_err("the operation fails").to_string(), "something went wrong");

Keep variant assertions for recovery contracts, and test structured payloads directly.

For semantic checks, both Exn and Error provide is_retryable(), is_not_found(), is_validation(), is_corrupted(), is_resource_exhausted(), is_cancelled(), is_permission_denied(), is_unauthenticated(), is_conflict(), and is_unsupported(). These inspect causes as well as the outermost error. is_retryable() requires an explicit retry classification; Exn::can_retry() and Error::can_retry() additionally recognize certain I/O error kinds. I/O errors with kind NotFound, OutOfMemory, PermissionDenied, or Unsupported receive corresponding semantic classifications; other kinds remain unclassified. For legacy credential-challenge I/O wrappers, an explicit Class::Unauthenticated anywhere in a PermissionDenied payload takes precedence over that wrapper’s native permission classification. The original I/O error remains available for downcasting; independently classified permission causes in its payload remain visible. Interrupted alone does not establish caller cancellation. Retry predicates also inspect original I/O kinds, but explicit cancellation takes precedence.

For application-level cancellation, use cancelled(). Preserve genuine I/O errors as causes. Classification itself neither clears interruption state nor retries.

use gix_error::ErrorExt;

let err = gix_error::cancelled("Cancelled by user").raise();
assert!(err.is_cancelled());
assert!(!err.can_retry());
assert!(!err.can_retry_lenient());

Use Exn::probable_cause() to inspect the likely root cause. It follows a single causal path, stopping at the first branch rather than choosing an arbitrary sibling. Classification markers are transparent to this selection. Exn::classify() and Error::classify() expose each known classification together with its original error. Custom payloads of std::io::Error are inspected too, including any nested Error trees.

Message supplies its own diagnostic and optional classification. In contrast, ClassificationMarker only supplies classification metadata. Prefer defining intrinsic classifications on error types you control:

  • For a leaf error or variant whose classification is part of its meaning, return a constant marker from std::error::Error::source(). This makes every construction site carry the classification without repeated tag() calls.
  • Use tag() when a classification depends on the calling context, or when you cannot modify the error type. It preserves the concrete error and its diagnostic.

For example, a caller may know that an AlreadyExists I/O error is retryable in its operation:

use gix_error::{Class, ClassificationMarker, ErrorExt, tag};

let err = tag(
    std::io::Error::from(std::io::ErrorKind::AlreadyExists),
    Class::Retryable,
).raise();
assert!(err.is_retryable());
assert!(err.probable_cause().is::<std::io::Error>());
assert!(err.downcast_any_ref::<ClassificationMarker>().is_none());
let classification = err.classify().next().expect("the tag is first");
assert!(classification.error().is::<std::io::Error>());
assert_eq!(classification.io_kind(), Some(std::io::ErrorKind::AlreadyExists));

Custom error types preserve classifications by exposing their immediate cause as Some(inner) from std::error::Error::source(). Forwarding to inner.source() instead can hide a classification carried by inner itself. A custom leaf error can borrow a constant such as ClassificationMarker::NOT_FOUND as its source to preserve its classification without defining a static or adding a generic category to its diagnostic:

use gix_error::{ClassificationMarker, ErrorExt};

#[derive(Debug)]
struct MissingObject;

impl std::fmt::Display for MissingObject {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("the requested object is missing from the object database")
    }
}

impl std::error::Error for MissingObject {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        Some(const { &ClassificationMarker::NOT_FOUND })
    }
}

let err = MissingObject.raise();
assert!(err.is_not_found());
assert!(err.probable_cause().is::<MissingObject>());
assert!(err.classify().next().expect("a classified owner").error().is::<MissingObject>());

Use classification predicates rather than downcasting to Message just to recognize a category: diagnostic iterators and downcasts skip all classification markers. Exception and test reports omit their wrappers too, while raw std::error::Error::source() chains retain them. Genuine classified errors remain causal and can still be downcast to inspect their payloads. When storing an Exn in a custom error, convert it with Exn::into_error() so the source can expose its complete tree.

Record offending input with Message::with_input(), then inspect the documented metadata key:

use gix_error::{ErrorExt, MetadataValue};

let err = gix_error::validation("invalid input").with_input(b"bad".as_slice()).raise();
let values = err.metadata().find(|values| values.contains_key("input")).expect("input context");
assert_eq!(values["input"], MetadataValue::Bytes(b"bad".as_slice().into()));

§Matching a specific failure

Downcast to the operation’s error enum and match a variant when a broad category such as Class::NotFound isn’t specific enough for recovery. The enum retains structured data and identifies the condition independently of diagnostic wording. For intrinsic classifications on leaf variants of an enum you define, prefer an exhaustive match on self in std::error::Error::source(), returning a constant marker as below. Each new variant then requires an explicit classification choice. Wrapping, erasure, and conversion to Error preserve the classification, so callers do not need to repeat it with tag().

use gix_error::{ErrorExt, message};

mod merge {
    use gix_error::ClassificationMarker;

    #[derive(Debug)]
    #[non_exhaustive]
    pub enum Error {
        MissingBinaryMergeResult,
    }

    impl std::fmt::Display for Error {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            match self {
                Self::MissingBinaryMergeResult => f.write_str("The binary merge result could not be selected"),
            }
        }
    }
    impl std::error::Error for Error {
        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
            match self {
                Self::MissingBinaryMergeResult => Some(const { &ClassificationMarker::NOT_FOUND }),
            }
        }
    }
}

fn recover(err: gix_error::Error) -> gix_error::Result<()> {
    match err.downcast_any_ref::<merge::Error>() {
        Some(merge::Error::MissingBinaryMergeResult) => Ok(()), // Apply the caller's fallback.
        _ => Err(err), // Preserve unfamiliar variants and all other errors.
    }
}

let err = merge::Error::MissingBinaryMergeResult.and_raise(message("Tree merge failed"));

assert!(err.is_not_found(), "the variant supplies its intrinsic classification");
assert!(
    matches!(err.downcast_any_ref::<merge::Error>(), Some(merge::Error::MissingBinaryMergeResult)),
    "the classified variant remains available for recovery"
);
recover(err)?;

Downcasting and types::Classification::error() retain concrete subjects through contexts and Error conversion. Matching one cause does not make other failures in an aggregate ignorable.

§Common Pitfalls

§Don’t use .erased() to change the Exn type parameter

Exn::raise() already nests the current Exn<E> as a child of a new Exn<T> without prior erasure. On native errors, use ErrorExt::and_raise() for an Error, or ErrorExt::and_raise_typed() for a typed exception.

Use .erased() when you need a type-erased Exn (no type parameter), e.g. when combining different failures in an exception tree. Otherwise return Result<T>.

§Don’t use .raise_all() with a single error

Exn::raise_all() is meant for creating error trees with multiple causes. If you only have a single causing error, use .or_raise() instead:

ⓘ
// WRONG — raise_all() is for multiple causes, not a single one:
result.map_err(|e| message("context").raise_all(Some(e.raise_typed())))?;

// RIGHT — or_raise() wraps the error with context directly:
result.or_raise(|| message("context"))?;

§Avoid conversions between diagnostic-only helpers

Use Result throughout a call chain unless callers need typed exceptions or exception-tree operations. Helpers can then return their callee’s result directly:

use gix_error::{message, Result, ResultExt};

fn parse_count(input: &str) -> Result<u64> {
    input.parse::<u64>().or_raise(|| message("could not parse count"))
}

pub fn count(input: &str) -> Result<u64> {
    parse_count(input)
}
assert_eq!(count("42")?, 42);

Concrete public exception signatures remain typed. Use ResultExt::or_error() when a callee returns such an exception and the caller returns Result. Error implements std::error::Error; Exn does not.

§Supporting types

Frequently used error types, extension traits, result aliases, and constructors are available at the crate root. Utility types for flattened chains, classification, and diagnostic display live in types. Exception frames and the default type-erasure marker live in exn; Exn and its extension traits are only exported at the root.

§Feature Flags

  • error-print-location — Print captured caller locations in diagnostics. Alternate formatting continues to omit locations. Locations are always captured and available for inspection, even without this feature.

  • bstr — Accept bstr::BString and bstr::BStr as byte metadata. Byte metadata always uses Vec<u8> with the same diagnostic formatting.

  • anyhow — The Exn type converts to anyhow::Error natively so ? can be used directly.

    Without this feature, use into_error() to convert it manually while preserving the error context and caller locations.

  • auto-chain-error — The Error type is always flattening the Exn error tree into a chain of errors, while keeping their locations and runtime type-information.

  • tree-error — The opposite of auto-chain-error and implicitly enabled by default. Use it to override auto-chain-error.

§Why not anyhow?

anyhow is a proven and optimized library, and it would certainly suffice for an error-chain based approach where users are expected to downcast to concrete types.

What’s missing though is track-caller which will always capture the location of error instantiation, along with compatibility for error trees, which are happening when multiple calls are in flight during concurrency.

Exn intentionally does not implement std::error::Error; the default helpers return Error, which does.

exn is much less optimized, but also costs only a Box on the stack, which in any case is a step up from thiserror which exposed a lot of heft to the stack.

Re-exports§

pub use bstr;

Modules§

exn
Frame inspection and type erasure for crate::Exn.
types
Utility types for error-chain interoperability, classification, and diagnostic display.

Macros§

bail
Creates an Exn and converts it to the function’s result error type.
ensure
Ensures $cond is met; otherwise return an error.
message
Construct a Message from a string literal or format string. Note that it always runs format!(), use the message() function for literals instead.

Structs§

ClassificationMarker
A transparent classification marker with an optional owned source and no diagnostic of its own.
Error
An error type that wraps an inner type-erased boxed std::error::Error or an Exn frame.
Exn
An exception type that can hold an error tree and the call site.
Message
A diagnostic message with an optional semantic class and named diagnostic values.
Metadata
An ordered dictionary of named diagnostic values belonging to a single error context.
TestError
An error for test functions that accepts any error supported by a boxed standard error.

Enums§

Class
The recovery approach suggested by an error.
MetadataValue
An owned scalar value in a Metadata dictionary. Bytes and native paths retain their original representation.
ResourceExhaustionKind
The kind of resource exhaustion which prevented an operation from completing.

Traits§

BoxedResultExt
Extension methods for results containing an already boxed error.
ErrorExt
Raise native errors with caller locations and optional context.
OptionExt
Raise errors lazily on Option::None.
ResultExt
Convert native errors and exceptions into public Results, or add context lazily on failure.

Functions§

allocation_failure
Create a diagnostic for an unrepresentable allocation size or memory that could not be reserved.
allocation_limit
Create a diagnostic for an exceeded application-configured allocation limit.
cancelled
The caller requested cancellation; stop rather than retry.
classify
Lazily inspect the classifications of any borrowed error, including its native sources, I/O payloads and nested crate::Error values. Unknown errors are omitted and distinct causes may yield the same classification.
conflict
Current state conflicts with the operation; refresh or reconcile state before retrying.
corruption
Create a diagnostic for malformed or internally inconsistent data, classified as Class::Corruption.
message
Return a new statically allocated message.
not_found
Create a diagnostic for a missing resource, classified as Class::NotFound.
permission_denied
Authorization or permissions are insufficient; obtain authorization or change permissions.
resource_exhaustion
Create a diagnostic for an exhausted resource, classified as Class::ResourceExhaustion of kind.
retryable
Create a diagnostic for an operation that may succeed when retried, classified as Class::Retryable.
tag
Add class to err, preserving its concrete type and diagnostic without a visible wrapper.
unauthenticated
Credentials are missing or rejected; obtain or refresh credentials.
unsupported
A required capability is unsupported; switch implementation, format, protocol, or strategy.
validation
Create a diagnostic for invalid function or method input, classified as Class::Validation.

Type Aliases§

ExnMessageResult
A result with a Message exception, defaulting to unit success.
ExnResult
A result with an Exn<E> error, defaulting to unit success and an erased error type.
Result
The result type for erased or message-based errors in plumbing and porcelain crates.
TestResult
A result type for test functions whose errors are reported through TestError’s complete diagnostics.