Live data from Hacker News

Rust errors without dependencies

vincents.dev

41–50 of 91 posts

Re: Rust errors without dependencies

#41

[flagged]

The entire blog shows that you don’t need that… sushi showed the same thing in 1.0

Go dosent deviate from the norm. It’s the same style we’ve had back from the billion dollar mistake. Not saying it’s wrong rust’s is just different. Tradeoffs and such.

Re: Rust errors without dependencies

#42

OP is spot on, no deps is the way. I've been using rust for 8+ years, I remember the experiments around `failure` crate, a precursor to anyhow if I remember right... and then eyre, and then thiserror... It just felt like too much churn and each one offered barely any distinction to the previous. Additionally, the `std::error::Error` trait was very poorly designed when it was initially created. It was `std` only and l…

> It was `std` only and linked to a concept of backtraces, which made it a non-started for embedded. It just seemed to me that it was a bad idea ever to use it in a library and that it would harm embedded users. It was never linked to backtraces. And if you used `std::error::Error` in a library that you also wanted to support in no-std mode, then you just didn't implement the `std::error::Error` trait when the `std`…

> I wrote about how to do error handling without libraries literally the day Rust 1.0 was published: https://burntsushi.net/rust-error-handling/ > > That blog did include a recommendation for `failure` at one point, and now `anyhow`, but it's more of a footnote. The blog shows how to do error handling without any dependencies at all. You didn't have to jump on the error library treadmill. (Although I will say that `anyhow` and `thiserror` have been around for a number of years now and shows no signs of going away.)

Thank you -- I just wanna say, I read a lot of your writing and I love your work. I'm not sure if I read that blog post so many years ago but it looks like a good overview that has aged well.

> I happily downcast in ripgrep: https://github.com/BurntSushi/ripgrep/blob/0a88cccd5188074de... > > That also shows the utility of an error chain.

Yeah, I mean, that looks pretty nice.

I still think the error chain abstraction should actually be a tree.

And I think they should never have stabilized an `std::error::Error` trait that was not in core. I think that itself was a mistake. And 8 years later we're only now maybe able to get there.

I actually said something on a github issue about this before rust 1.0 stabilization, and that it would cause an ecosystem split with embedded, and that this really should be fixed, but my comment was not well received, and obviously didn't have much impact. I'll see if I can find it, it's on github and I remember withoutboats responded to me.

Realistically the core team was under a lot of pressure to ship 1.0 and rust has been pretty successful -- I'm still using it for example, and a lot of embedded folks. But I do think I was right that it caused an ecosystem split with embedded and could have been avoided. And the benefit of shipping a janky version of `std::error::Error` however many years ago, almost all of which got deprecated, seems hard to put a finger on.

Re: Rust errors without dependencies

#43
post #37
post #34

Earlier quoted context omitted.

> Unless somehow these are compromised at the time of download, I will never have to worry about them again. But this is exactly what rust does x) `cargo add some_crate` adds a line `crate_name = "1.2.3"` to your project config, downloading and pinning the dependency to that exact version. It will not change unless you specifically change it.

well, not quite. It'll go into the lockfile and you won't get a new version if you just build again, but if you add or remove a dependency that version may shift around a bit as a part of dependency resolution.

Only if that different version is a dependency of a dependency. Your own will never change.

Re: Rust errors without dependencies

#44
post #37
post #34

Earlier quoted context omitted.

> Unless somehow these are compromised at the time of download, I will never have to worry about them again. But this is exactly what rust does x) `cargo add some_crate` adds a line `crate_name = "1.2.3"` to your project config, downloading and pinning the dependency to that exact version. It will not change unless you specifically change it.

well, not quite. It'll go into the lockfile and you won't get a new version if you just build again, but if you add or remove a dependency that version may shift around a bit as a part of dependency resolution.

> but if you add or remove a dependency that version may shift around a bit as a part of dependency resolution

  cargo add crate@version
is completely deterministic

Re: Rust errors without dependencies

#45
post #25

Earlier quoted context omitted.

I'm on libs-api and I'd personally be on board with something like `thiserror` coming into `std`. But it would need a champion I think.

I think we should provide the building blocks (display, etc like derive_more) rather than a specialized version one for errors (thiserror). I also feel thiserror encourages a public error enum which to me is an anti-pattern as they are usually tied to your implementation and hard to add context, especially if you have a variants for other error types.

I don't quite understand the issue about public error enums? Distinguishing variants is very useful if some causes are recoverable or - when writing webservers - could be translated into different status codes. Often both are useful, something representing internal details for logging and a public interface.

Re: Rust errors without dependencies

#46

Earlier quoted context omitted.

By error accumulation, I mean a tree of errors, not a simple chain. The chain is only useful at the very lowest level. The tree allows you to say e.g. this function failed because n distinct preconditions failed, all of which are interesting, and might have lower level details. Or, I tried to do X which failed, and the fallback also failed. The error chain thing doesn’t capture either of these semantics properly. Che…

I don't see any reason for something like `rootcause` to become foundational. Most errors are a linear chain and that's good enough for most use cases. It's correct to say that `std::error::Error` does not support a tree of errors. But it is incorrect to say what you said: that it's pointless and doesn't allow error accumulation . It's not pointless and it does provide error accumulation. Saying it doesn't is a broad…

There's a semantics discussion about whether progressively adding context to errors (forming an error chain) counts as "error accumulation" or if error accumulation means collecting several errors that occurred and returning that to the caller. But at this point I think you understand what I meant and I understand your meaning.

I do think that `std::error::Error` is mostly pointless. That's a value judgment, and reasonable people can disagree.

I've tried to argue that, it can create bigger problems then it solves. It's a trait that only exists on platforms with `std`. That itself is pretty nasty and if you care at all about platforms that aren't like that, you're taking on a lot of build complexity. If you really need this why not just make your own `trait HasCause` which is like a subset of `std::error::Error` functionality, and simply doesn't require `std`?

I'll list a number of things that I've experienced coworkers being confused about around the `std::error::Error` trait.

1) Why does it require `Display` and then not use it?

2) Displaying it is very simple: `format!("{err}")`. If you want to format the error and it's chain of causes, actually using the `std::error::Error` functionality, the recommended way was to use yet another experimental `error_chain` library. When should we actually do that? When is that appropriate?

Now we have a place where there's two different ways to do the same thing (display an error). Additionally there is controversy and churn around it.

In a large project, most developers will be completely ignorant about the second more obscure possibility. And in most projects, you don't really need two ways to format an error. So I tend to do the friendliest thing for developers. There is only one way, and it is Display, which 100% of rust developers know about, and I avoid using `std::error::Error`.

I understand that there's a bright shiny future that people hope it's headed for, where everything around `std::error::Error` is easy and obvious, and we have powerful flexible expressive ergonomic error handling. I was excited about that like 7 years ago, now I just kinda want to change the channel. I'm glad some people still find some benefit in the small improvements that have occurred over time... and I hope in 8 more years there's more to the story than where we are today.

Re: Rust errors without dependencies

#47
The fact that you either need a third party dependency or a large amount of boilerplate just to get decent error reporting, points to an issue in the language or std library design.

I've started also dropping `thiserror` when building libraries, as I don't want upstream users of my libraries to incur this additional dependency, but it's a pain.

Re: Rust errors without dependencies

#48

My controversial take on Rust errors is to use anyhow everywhere until you have an immediate demand for explicit Enums. YANGNI The pros for using anyhow are big: Easily stack errors together - eg file.open().context(path) -, errors are easily kept up to date, and easy to find where they occur. An enum error is pleasing when you're finished, but cumbersome in practice. It's niche situation that you need to write a fun…

Yeah, I’m the same. I default to anyhow unless I need a strong API boundary (like if I’m publishing a library crate)

Sure, it’s slightly more error prone than proper enum errors, but it’s so much less friction, and much better than just doing panic (or unwrap) everywhere.

Re: Rust errors without dependencies

#49

The fact that you either need a third party dependency or a large amount of boilerplate just to get decent error reporting, points to an issue in the language or std library design. I've started also dropping `thiserror` when building libraries, as I don't want upstream users of my libraries to incur this additional dependency, but it's a pain.

Why are people disagreeing with this? This is absolutely a problem that most other languages don't have. If you want to claim that Rust's error system is "better" than anything else (as the author did), you should have a good argument about why this exact problem the parent commenter described, which to me is a major problem, does not (maybe) cancel out all the other purported benefits of Rust's error system!

Re: Rust errors without dependencies

#50
post #43
post #37

Earlier quoted context omitted.

well, not quite. It'll go into the lockfile and you won't get a new version if you just build again, but if you add or remove a dependency that version may shift around a bit as a part of dependency resolution.

Only if that different version is a dependency of a dependency. Your own will never change.

That does not make the problem go away: now you'll have both versions in your dependency graph - hence you may be vulnerable to both version's CVEs.
Post reply on HN