Best practices on failing fast during start up

Programming is hard and anything can go wrong, so the functions I call from main oftentimes return a Result or an Option.

I deal with it like this FooBuilder::new().build().expect("Failed to initialize foo"). But this produces rather user unfriendly error messages like thread '<main>' panicked at 'Failed to init the foo.

Is there any convenient way of producing human error? Should I implement something like

impl UserFacingError {
    fn report_error_to_stderr(self) {


Or is there a tiny crate for the job?

Personally, I just bubble an std::error::Error and print it at the top with:

// Errors implement Display
writeln!(::std::io::stderr(), "Error: {}", e); 

Panics should generally be reserved for program errors and, IMO, should look unfriendly.