Idiomatic way to ignore certain kinds of errors?

For example, I want to remove a UNIX socket file, ignoring "file not found" errors (just like what rm -f does). But at the same time, I want all other kinds of errors (e.g. permission denied, file in use) to be reported as is.

What's the idiomatic way to do this? This is what I'm currently doing:

match std::fs::remove_file("/tmp/server.sock") {
    Err(err) if err.kind() != ErrorKind::NotFound => {
        panic!("failed to remove /tmp/server.sock: {}", err);
    }
    _ => (),
}

I might invert the logic here:

match std::fs::remove_file("/tmp/server.sock") {
    Err(err) if err.kind() == ErrorKind::NotFound => (),
    r => r?,
};

2 Likes

Disclaimer: I'm still new to Rust. I would do have written:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    std::fs::remove_file("testfile").or_else(|err| {
        if err.kind() == std::io::ErrorKind::NotFound {
            Ok(())
        } else {
            Err(err)
        }
    })?;
    Ok(())
}

Or, if you want to panic:

fn main() -> () {
    std::fs::remove_file("testfile")
        .or_else(|err| {
            if err.kind() == std::io::ErrorKind::NotFound {
                Ok(())
            } else {
                Err(err)
            }
        })
        .expect("failed to remove testfile");
}

Note that the expect method will add the error description in case of a panic:

thread 'main' panicked at 'failed to remove testfile: Os { code: 1, kind: PermissionDenied, message: "Operation not permitted" }', src/main.rs:10:10

But looking at @2e71828's reply theirs seems much shorter than my approach… So perhaps that's better or at least a good alternative.

So maybe I shouldn't underestimate the power of using manual pattern matching instead of using methods like or_else and the like. The advantage of match is that you can throw an error inside one of the branches (through r => r?).

Combining @2e71828's short proposal with throwing a panic using expect (if you want to panic instead of handling the error), it would be:

fn main() -> () {
    match std::fs::remove_file("testfile") {
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => (),
        r => r.expect("failed to remove testfile"),
    }
}

But handling the error should be preferred!

Thanks everyone for your suggestions!