How do I filter by a specific error enum in a match arm?

Context: I'm making a CLI application and am having trouble with error handling in terms of filtering match arms by error type.

Let's say say I have a function which returns a Box<error::Error> as follows:

use std::error;

fn cli(cli_args: Vec<String>) -> Result<(), Box<error::Error>> {
    // A lot of code that can result in a variety of errors
    Ok(())
}

For argument parsing, I use the popular clap-rs library, and use the ? operator on get_matches_from_safe. My main function is as follows:

use std::{env, process};

fn main() {
    let exit_code = match cli(env::args().collect::<Vec<_>>()) {
        Ok(_) => 0,
        Err(err) => {
            print!("{:?}", err);
            1
        }
    };
    
    process::exit(exit_code);
}

Currently, whenever an error occurs from clap, a clap::Error is generated. Is there any way to match for any clap::Error in the Err arm? I don't want to individually check every variant of the enum, I just want to match on any of them.

You've a few options:

  1. Define your own enum with a variant for clap::Error, and match on that
  2. Use Error::downcast() in your match statement to dynamically check if it's clap::Error.

#2 can look something like:

let exit_code = match cli(env::args().collect::<Vec<_>>()) {
        Ok(_) => 0,
        Err(err) => {
            match err.downcast::<clap::Error>() {
                Ok(clap) => println!("clap err: {}", clap),
                Err(other) => println!("other: {}", other),
            };
            1
        }
    };

clap::Error is a struct - you're probably thinking of clap::ErrorKind, which is an enum - but you don't need to do anything with it if you don't want.

1 Like

This solution works! Thanks! I combined it with an if let to make it more readable, though.