DEV Community

Discuss: How should you handle errors in your library code?

Max on May 09, 2019

I like to work on open source projects in my free time and thus have created a few JavaScript modules in the past. Most of the times, they're like ...
Collapse
 
dmfay profile image
Dian Fay

Throw or reject, all the way. Libraries generally shouldn't control the process, but the other mechanisms you've identified for surfacing "hard errors" are the standard. It's on the consumer to ensure that they account for exceptional behavior where it's possible for it to occur, especially where that depends on input from the consumer.

Returning a string message is a non-standard and therefore inferior variation on proper exception raising. Ignoring or second-guessing invalid input is the stuff of which nightmares are made. Imagine somebody using your timezone code to manage flight schedules: a time and invalid timezone come in from, say, Chongqing, you've decided to ignore invalid timezones, the code returns a "UTC" time that's actually eight hours ahead, that makes it into a central database, and suddenly air traffic control's day is a lot more interesting.

Collapse
 
maxrimue profile image
Max

Thanks for your input! I think that makes sense what you say. To explain: the original motivation behind tizo was to be as easy to use for it's use case as possible, which is why I expect a string formatted in various possible ways instead of expecting the user to do the interpreting, but that puts me into this situation where i/o becomes hard to predict.

Collapse
 
dmfay profile image
Dian Fay

That's understood! The important principle here is that a library shouldn't do anything surprising. Something going wrong or being irresolvable may be a surprise in one sense, but raising an error so the consumer can decide what to do about it is the expected course of action for library code in that circumstance: you're not adding another surprise on top. Conversely, hiding errors or anticipating the user may afford a pleasant surprise sometimes, but you can't guarantee that it'll always be that way.

Collapse
 
nexdrew profile image
Andrew Goode

Generally I agree with Dian, but I think it depends on the API you want to use. Using moment or luxon as an example, when a string can't be parsed into a valid value, they return a special object that is "invalid", which you can check with .isValid - I can see arguments for both sides of this coin, but it at least allows the consumer to write a branch of logic that does not require catching an error (or handling a Promise rejection).

For your libraries, you could have 2 API methods - one that throws and one that doesn't - as long as it's clearly documented, you can let the consumer decide which they prefer.

Collapse
 
maxrimue profile image
Max

That sounds like a great idea, I will try that! This distinction in API would probably also help make clear the operation itself is rather "guesswork". Also, I like offering a "strict" API with "strict" (or as I called them, hard) errors, and the opposite with the opposite type of error handling.

Maybe the conclusion to this discussion here is, that error handling should be just as strict as the API itself? Make a "magic infer" function that guesses in the worst case, and an argument based one that throws when clearly defined requirements are not met.