Rust - anyhow

This chapter presents usage of anyhow crate.

Objectives

  • Implement a chain of functions where one calls another.
  • Return an error from the innermost function.
  • Add context to the errors on each subsequent level.
  • Handle the error on the top level by displaying all the causes.
  • Consider std::io::Error as well as user-defined error as a root cause.

Implementation

// config.rs
use anyhow::{Result, Context, bail};

pub fn load_config() -> Result<()> {
    let path = "myconfig";  
    let _text = std::fs::read_to_string(path)
        .context(format!("Failed to read config file: {}", path))?;
        
    let key = "foo";
    bail!("Unknown key '{}'", key);
}
// setup.rs
use anyhow::{Result, Context};

use crate::config;

pub fn setup_app() -> Result<()> {
    Ok(config::load_config().context("Failed to configure")?)
}
// launcher.rs
use anyhow::{Result, Context};

use crate::setup;

pub fn launch_app() -> Result<()> {
    Ok(setup::setup_app().context("Failed to setup application")?)
}
// main.rs
use anyhow::Result;
mod config;
mod setup;
mod launcher;

fn main() -> Result<()> {
    launcher::launch_app()
}

Testing

$ cargo build
$ ./target/debug/anyhow_demo
Error: Failed to setup application

Caused by:
    0: Failed to configure
    1: Failed to read config file: myconfig
    2: No such file or directory (os error 2)

$ touch myconfig
$ ./target/debug/anyhow_demo
Error: Failed to setup application

Caused by:
    0: Failed to configure
    1: Unknown key 'foo'