Comment by tptacek
19 hours ago
He's not making that up; in practice, you're going to run into and need to make mental space for the idiosyncrasies of multiple error frameworks.
19 hours ago
He's not making that up; in practice, you're going to run into and need to make mental space for the idiosyncrasies of multiple error frameworks.
Not sure what you mean by that. If you're consuming the API of a crate that has functions that return errors, you're not really dealing with a "framework", you're just dealing with whatever the `E` is in the `Result<T, E>`. If that `E` doesn't implement std::error::Error, I'd consider that a deficiency (even a bug) for that crate. (Yes, I know some crates want to support use in `no_std` environments; that's what features are for.)
If I care about the specific variants of error that a function can return, so I can do different things depending on what kind of error occurred, I'll read the docs and match. That's not really a "framework" thing; that's just a basic thing that anyone has to do in any language in order to consume an API. If I need to propagate the error, I'll do so (either directly, or by wrapping it in a variant of my own error type). I don't see how any of this is "framework"-y.
A crate's decision to use thiserror (or not) does not matter to me. If a crate exposes `anyhow::Error`, that's a lazy choice and bad API design, but still "works" and I generally don't need to care about it.
Or is there something else you meant when you said "error frameworks"?
Just wanted to add that `Error` has been in core since `1.81` [1], meaning that even `no_std` environments can/should represent errors the same way.
[1] https://doc.rust-lang.org/core/error/trait.Error.html
I guess you might have to if you need to use a library someone's written that doesn't implement the standard.
Writing primarily applications, I couldn't tell you what error handling frameworks my dependencies are using: I literally don't know, and haven't needed to know in order to display, fail, or succeed.
EDIT to add: I use anyhow for this, so I should also add "add context to an error when I fall" to the list of things I do.
What's the standard? I'm not being snarky; I'm going down the thought process of how this would work in practice.
I am on team Io Error [on std rust]", somewhat arbitrarily. If I call a lib that is on Team Anyhow, or Team Custom Error Enum, I will have to do some (Straightfoward, but a little clumsy) conversions if I want ? to work. This is complicated by being able to impl From<ErrorType1> for ErrorType2 only in one direction if you don't control the other crate. (due to the orphan rule)
By standard I meant an error type that implements std::error::Error.
EDIT: Which I assume all my dependencies have done, given that anyhow is able to consume all of them.
I specifically called out writing applications as my use case: my only objection to tptacek's note is the somewhat universal "in practice". The burden for designing errors for a library that others will use is higher, but that's far from the default/universal experience.
Many more people are going to consume libraries & not produce any of their own, and I think my experience is representative there.
There is no team io::Error. There is only one standard: https://doc.rust-lang.org/core/error/trait.Error.html
Not rust specific, and most certainly not a criticism of you - but I hate when people call a lib that errors, then just bubble that error up.
I mean the error is supposed to be tailored to the audience - I guess what you are saying is that you handle the error by saying "I called foo with X, Y, Z, and got this error back" in the logs - which your caller then also does - producing a log message of
ERROR: I called Foo with X Y and Z and got error: Die MF die
followed by
ERROR: I called Bar with X Y Z and a and got error: ERROR: I called Foo with X Y and Z and got error: Die MF die mf (still fool)
And so on and so forth.
If the counter is - don't log, that's fine, but you have to know where in the call graph that error state was reported to the logs
I have tried to figure out some kind of unification between "collecting error state in a function", "logging error state", and "return error state to a parent".
I haven't found any satisfying solution to it all; collecting information for logging vs information that a caller would want... I've been meaning to investigate tracing_error to see if it brings it all together.
1 reply →
You’re supposed to bubble errors up to the level that can appropriately deal with them? You don’t need to log them each step of the way.
1 reply →