anyhow 1.0.7

A better Box<dyn Error>
Documentation

Anyhow ¯\_(ツ)_/¯

Build Status Latest Version Rust Documentation

This library provides anyhow::Error, a trait object based error type for easy idiomatic error handling in Rust applications.

[dependencies]
anyhow = "1.0"

Compiler support: requires rustc 1.34+

Details

  • Use Result<T, anyhow::Error>, or equivalently anyhow::Result<T>, as the return type of any fallible function.

    Within the function, use ? to easily propagate any error that implements the std::error::Error trait.

    use anyhow::Result;
    
    fn get_cluster_info() -> Result<ClusterMap> {
        let config = std::fs::read_to_string("cluster.json")?;
        let map: ClusterMap = serde_json::from_str(&config)?;
        Ok(map)
    }
    
  • Attach context to help the person troubleshooting the error understand where things went wrong. A low-level error like "No such file or directory" can be annoying to debug without more context about what higher level step the application was in the middle of.

    use anyhow::{Context, Result};
    
    fn main() -> Result<()> {
        ...
        it.detach().context("failed to detach the important thing")?;
    
        let content = std::fs::read(path)
            .with_context(|| format!("failed to read instrs from {}", path))?;
        ...
    }
    
    Error: failed to read instrs from ./path/to/instrs.jsox
    
    Caused by:
        No such file or directory (os error 2)
    
  • Downcasting is supported and can be by value, by shared reference, or by mutable reference as needed.

    // If the error was caused by redaction, then return a
    // tombstone instead of the content.
    match root_cause.downcast_ref::<DataStoreError>() {
        Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
        None => Err(error),
    }
    
  • A backtrace is captured and printed with the error if the underlying error type does not already provide its own. In order to see backtraces, the RUST_LIB_BACKTRACE=1 environment variable must be defined.

  • Anyhow works with any error type that has an impl of std::error::Error, including ones defined in your crate. We do not bundle a derive(Error) macro but you can write the impls yourself or use a standalone macro like err-derive.

    #[derive(Error, Debug)]
    pub enum FormatError {
        #[error(display = "invalid header (expected {:?}, got {:?})", expected, found)]
        InvalidHeader {
            expected: String,
            found: String,
        },
        #[error(display = "missing attribute: {}", _0)]
        MissingAttribute(String),
    }
    
  • One-off error messages can be constructed using the anyhow! macro, which supports string interpolation and produces an anyhow::Error.

    return Err(anyhow!("missing attribute: {}", missing));
    

Comparison to failure

The anyhow::Error type works something like failure::Error, but unlike failure ours is built around the standard library's std::error::Error trait rather than a separate trait failure::Fail. The standard library has adopted the necessary improvements for this to be possible as part of RFC 2504.

Acknowledgements

The implementation of the anyhow::Error type is originally forked from fehler::Exception (https://github.com/withoutboats/fehler). This library exposes it under the more standard Error / Result terminology rather than the throw! / #[throws] / Exception language of exceptions.

License