[][src]Crate thiserror

This library provides a convenient derive macro for the standard library's std::error::Error trait.


Example

use thiserror::Error;

#[derive(Error, Debug)]
pub enum DataStoreError {
    #[error("data store disconnected")]
    Disconnect(#[from] io::Error),
    #[error("the data for key `{0}` is not available")]
    Redaction(String),
    #[error("invalid header (expected {expected:?}, found {found:?})")]
    InvalidHeader {
        expected: String,
        found: String,
    },
    #[error("unknown data store error")]
    Unknown,
}

Details

  • Thiserror deliberately does not appear in your public API. You get the same thing as if you had written an implementation of std::error::Error by hand, and switching from handwritten impls to thiserror or vice versa is not a breaking change.

  • Errors may be enums, structs with named fields, tuple structs, or unit structs.

  • A Display impl is generated for your error if you provide #[error("...")] messages on the struct or each variant of your enum, as shown above in the example.

    The messages support a shorthand for interpolating fields from the error.

    • #[error("{var}")] ⟶ write!("{}", self.var)
    • #[error("{0}")] ⟶ write!("{}", self.0)
    • #[error("{var:?}")] ⟶ write!("{:?}", self.var)
    • #[error("{0:?}")] ⟶ write!("{:?}", self.0)

    These shorthands can be used together with any additional format args, which may be arbitrary expressions. For example:

    #[derive(Error, Debug)]
    pub enum Error {
        #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::max_value())]
        InvalidLookahead(u32),
    }

    If one of the additional expression arguments needs to refer to a field of the struct or enum, then refer to named fields as .var and tuple fields as .0.

    #[derive(Error, Debug)]
    pub enum Error {
        #[error("first letter must be lowercase but was {:?}", first_char(.0))]
        WrongCase(String),
        #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)]
        OutOfBounds { idx: usize, limits: Limits },
    }
  • A From impl is generated for each variant containing a #[from] attribute.

    Note that the variant must not contain any other fields beyond the source error and possibly a backtrace. A backtrace is captured from within the From impl if there is a field for it.

    #[derive(Error, Debug)]
    pub enum MyError {
        Io {
            #[from]
            source: io::Error,
            backtrace: Backtrace,
        },
    }
  • The Error trait's source() method is implemented to return whichever field has a #[source] attribute or is named source, if any. This is for identifying the underlying lower level error that caused your error.

    The #[from] attribute always implies that the same field is #[source], so you don't ever need to specify both attributes.

    Any error type that implements std::error::Error or dereferences to dyn std::error::Error will work as a source.

    #[derive(Error, Debug)]
    pub struct MyError {
        msg: String,
        #[source] // optional if field name is `source`
        source: anyhow::Error,
    }
  • The Error trait's backtrace() method is implemented to return whichever field has a type named Backtrace, if any.

    use std::backtrace::Backtrace;
    
    #[derive(Error, Debug)]
    pub struct MyError {
        msg: String,
        backtrace: Backtrace, // automatically detected
    }
  • See also the anyhow library for a convenient single error type to use in application code.

Derive Macros

Error