Error

Derive Macro Error 

Source
#[derive(Error)]
{
    // Attributes available to this derive:
    #[error]
}
Expand description

Derive the Error trait for a struct.

The #[derive(Error)] macro provides a declarative way to implement both the Error and Display traits for your custom error types. It is controlled by #[error(...)] type-level attributes that specify how the error should behave.

§General form

#[derive(Error, Debug)]
#[error("a formatted message {arg}", arg)]
// #[error(source(...))]
// #[error(transparent(...))]
// #[error(from)]
struct MyError { /* fields */ }

The attribute syntax follows the form:

#[error(<parameter>)]

Multiple #[error(...)] attributes can be applied to the same type, and are classified according to their parameter kind.

§Attribute kinds

The following attribute kinds are supported:

§#[error("...")] - format string

Provides a Display implementation for the error type, using Rust formatting syntax. Additional expressions may be listed as comma-separated arguments.

#[derive(Error, Debug)]
#[error("failed to read file: {path}")]
struct ReadError {
    path: String,
}

Expands to:

impl std::fmt::Display for ReadError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "failed to read file: {}", self.path)
    }
}

§#[error(source(<field>))] - source field

Declares which field represents the underlying cause of the error. This field will be returned from Error::source.

#[derive(Error, Debug)]
#[error("network request failed")]
#[error(source(io))]
struct NetworkError {
    io: std::io::Error,
}

Produces:

impl std::error::Error for NetworkError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        Some(&self.io)
    }
}

§#[error(transparent(<field>))] - transparent wrapper

Makes the error type a transparent wrapper around one of its fields. Both Display and Error are forwarded directly to that field.

#[derive(Error, Debug)]
#[error(transparent(0))]
struct Wrapper(std::io::Error);

This makes Wrapper behave exactly like its inner error for formatting and chaining purposes.

§#[error(from)] conversion

Requests that a From<T> implementation be generated for a specified field type, allowing automatic conversion into the error type.

#[derive(Error, Debug)]
#[error("parse failed")]
#[error(from)]
struct ParseError {
    inner: std::num::ParseIntError,
}

Allows:

let err: ParseError = "abc".parse::<u32>().unwrap_err().into();

§Enums

Enums may use the same attribute kinds at the variant level. Each variant can provide its own formatting, source, or transparency.

#[derive(Error, Debug)]
enum MyError {
    #[error("invalid input: {_0}")]
    InvalidInput(String),

    #[error(transparent(inner))]
    Io {
        inner: std::io::Error,
    },

    #[error("other error")]
    Other,
}

§Inline options

Inline behavior for generated methods can be controlled using:

#[derive(Error, Debug)]
#[error(inline(always))]
#[error("{msg}")]
struct FastError {
    msg: &'static str,
}

Valid values are:

  • neutral (default) → #[inline]
  • always#[inline(always)]
  • never#[inline(never)]

When omitted, no explicit #[inline(...)] attribute is emitted.

§Root import

All generated code defaults to using ::core. This can be overridden:

#[derive(Error, Debug)]
#[error("{msg}")]
#[error(import(::std))]
struct StdError {
    msg: &'static str,
}

This allows compatibility with std::error::Error where desired.