I'm building a small internal library that takes CSV data and writes it into a xlsx workbook, and I wrote a function called read_csv_into_excel.
The function can error in several ways including:
io error if the file can't be found/read
csv error if there's a csv parsing problem
parse error if the data in the csv can't be converted to f32
xlsx error if I can't write to the worksheet
My initial thought was to use anyhow, but as I understand that's not considered best practice for a library... so I thought I'd use thiserror and make a simple error-holder:
Which compiles and runs... but I'm wondering if this is the correct approach. If it's possible to have these disconnected types of errors, and I'm just forwarding their display data anyway... would I be better off shoving them into a Box<dyn Error> and just returning that?
Are there any pros/cons to each? What do most libraries in the rust ecosystem do for this?
Your question isn't necessarily thiserror specific. thiserror is primarily a tool to cut down on the boilerplate. You can do what it does yourself.
For a surface level suggestion, given the code you've shared -- does each error only happen based on a particular operation? You could at least add minimal context if so.
In my honest opinion though, the real answer comes down to how much effort you're willing to put in to get great errors, and how much you care about backwards compatibility given that this is an internal library. If you don't care about backwards compatibility at all, you can start with your current enum (or even Box<dyn Error>) and freely iterate over time to improve your errors.
And in my experience, you're probably are going to want to improve the errors eventually, even if this is for personal use. What file had an error, what line had an error... being told things like that are often significant QOL improvements.
But I don't think there's an easy path to having great errors. For great errors you need different error types for different operations, and to add context at each error site (like file names and line numbers), and also for nested errors (backtrace-like functionality). It takes a lot more thought up front, especially if you can't iterate freely.