Open emk opened 6 years ago
I've just merged #54, which implements a causes iterator. I think something like this would be adequate for your use case for now:
let mut stderr = io::stderr();
for fail in err.causes() {
let _ = writeln!(stderr, "{}", fail);
}
For reference, with #54 here is an approximation (meaning I haven't built it) of error-chain:
// Decide which command to run, and run it, and print any errors.
if let Err(err) = run(&args) {
let mut stderr = io::stderr();
let mut causes = err.causes();
writeln!(stderr, "Error: {}", causes.next().expect("`causes` to at least contain `err`"))
.expect("unable to write error to stderr");
for cause in causes {
writeln!(stderr, "Caused by: {}", cause)
.expect("unable to write error to stderr");
}
// The following assumes an `Error`, use `if let Some(backtrace) ...` for a `Fail`
writeln!(stderr, "{:?}", backtrace)
.expect("unable to write error to stderr");
process::exit(1);
}
The error-chain is my favorite feature in error-chain
.
I remember rustup
failing to download a file from behind the company's proxy and instead of getting the usual misleading error: No such file or directory
, I got a very clear chain of errors explaining that:
It made it extremely easy for me to fix the root cause.
Edit(the rustup output when I remove the SOCKS4 proxy):
error: could not download file from 'https://static.rust-lang.org/rustup/release-stable.toml' to '/tmp/rustup-update.T7Ry8gjuIytx/release-stable.toml'
info: caused by: error during download
info: caused by: [7] Couldn't connect to server (Failed to receive SOCKS4 connect request ack.)
Thank you for digging into this tricky design problem!
I miss the "chained" error display provided by
quick_main!
inerror-chain
. A lot of my software has been designed around showing the various nested error messages. For example:Showing the full context of the error provides helpful clues to the user. But
failure
provides no easy way to get that string, and it seems to encourage the use of errors like:This is less ergonomic for users.
One workaround is to write something like this:
This is potentially related to #41.
I don't think it's necessary to go as far as
quick_main!
. It might be enough to have adisplay_with_causes
method or even aDisplayWithCauses
newtype, allowing us to write something like:Obviously some of this could be provided by an external crate. But there might be some nice ergonomic improvements to be made here.