Returning more helpful error messages from try!


#1

I’ve written a program to import two text files and merge one into the other. I’m using try! macros to handle cases where one of the input files specified doesn’t exist.

let js_path = args.flag_js; //Determined with docopt
let mut js_file = try!(fs::File::open(js_path));

The error that try! returns if I enter a filename that doesn’t exist is:

Error { repr: Os(2) }

Well, that’s not particularly helpful. I’d like to specify something like:

let mut js_file = try!(fs::File::open(js_path, "Error: JS file not found");

Obviously that’s not part of the try! macro. Is there any already existing best practice for sending custom error messages like that? The closest I’ve gotten was:

macro_rules! try_or {
    ($expr:expr, $error_msg:expr) => (match $expr {
        Ok(val) => val,
        Err(_err) => {
            return Err(Error::new(ErrorKind::NotFound, $error_msg) );
        }
    })
}

But I’m not sure how to return just the StringError from that. println!("{:?}",error) will just give me

Error { repr: Custom(Custom { kind: NotFound, error: StringError("JS file not found") }) }

which is a little more helpful, but I’d still like to trim the fat and just spit out the string.


#2

Well I just sort of answered my own question.

macro_rules! try_or {
    ($expr:expr, $error_msg:expr) => (match $expr {
        Ok(val) => val,
        Err(_err) => {
            panic!($error_msg);
        }
    })
}

Duh.

Still spits out the thread '<main>' panicked at noise, though, so I’m still interested in a good way to only spit out the error string. Or if there’s another preferred way to do this.


#3

You probably want to use println!("{}", error) to print the error in a more user friendly fashion. println!("{:?}", error) uses the error’s Debug impl instead of its Display impl, which is why it’s printing the gritty details.

On beta, println!("{}", error) (where error is the error returned by open) gives me No such file or directory (os error 2).

Also, failing to open a file doesn’t necessarily mean it doesn’t exist. E.g., if a file exists but the user doesn’t have the correct permissions to read the file, printing Error: JS file not found would be rather confusing.