A growing number of libraries are returning exception structs to report errors so you can aggregate them more easily (easily testable via the Elixir built-in `Exception.is_exception?/1`) since the error tuples would start to get large and unwieldy when holding a lot of data, and since you can pack a lot in to exception structs it is becoming more common. See the library of
https://github.com/expede/exceptional for one example that has popped up to use that style, it allows operating on and over things that might be error tuples, exception structs, and a few other styles, so you can operate over a thing in a pipeline regardless of if the value has failed. An example (you have the optional to override `|>` with the exceptional library though it does not recommend it, its `~>` is the monadic style `|>` by default, so you can replace `|>` with `~>` everywhere if you want:
```elixir
this_might_fail() # Say this returns a success tuple of {:ok, blah} or {:error, blorp}
~> this_might_also_fail() # This could return a single successful value, or an exception structure
~> this_always_works() # This just mutates the value
~> blorp() # This returns a success or failure tuple like the first call above
~> bloop() # This just transforms the value but otherwise works fine
```
Thus without needing to do a huge amount of case statements (though nowadays the `with` construct could do this specific example, though `with` cannot do other things that `exceptional` can do) you can pipe a value through a set of calls, and if any fail then it fails out with that error without performing the later calls. Exceptional also has functions to normalize the value to a value|%Exception_struct{} or you can normalize it to a {:ok, value}|{:error, exception_message} or you can normalize is to a value or a raised exception as well, and a few other things. You can also invert it and use an exceptional def to define functions that handle it properly without using `~>`, good for libraries.
Its an odd style yes, but it was designed for easy piping and readability in mind. Personally I'd be a fan of using {:ok, success:any()}|{:error, messages:map()} or something like that everywhere, but there are so many styles (even of just error tuples I've seen many N-tuple sizes, many different kinds of errors, very irritating to keep reformatting each individually for error display and so forth, which is why I've been personally been moving over time to the style of returning a {:ok, value} 2-tuple for a success case always and a {:error, %SomeException{}} for the error case always, reason is that the exception contains all of the information you need to debug it as well as it is easily formatable (using Elixir's built-in `Exception.message/1`) to a text format for easy displaying to the user as well. Though this specific style is not as popular as returning the raw value or the exception struct directly, which is the growing style among a few things.