Proposed new dependency: github.com/juju/errors (and github.com/juju/errgo)

roger peppe roger.peppe at canonical.com
Thu May 29 08:11:14 UTC 2014


On 28 May 2014 19:40, Nate Finch <nate.finch at canonical.com> wrote:
> I think the main problem with errgo as it exists, is that it is very awkward
> to allow error type information to pass through:
>
>      return errgo.Mask(err, errgo.Any)
>
> This line is very misleading.  It's saying - mask the error type, except
> wait, actually don't mask the type.  It's never a good idea to use a
> function to do the opposite of what it's name says it does.

That's partly why I originally called the function "Wrap", but was
persuaded to change it to Mask by popular request.
And, I've said this before and I'm sure I'll say it again - it's
actually very rare to need to return *any* error type information
to pass through. When I changed all of juju to work this way,
there were about 5 occurrences out of hundreds, and all were
for good and understandable reasons.

> Instead, it would be much better to have a method like this:
>
>    errgo.MaintainErrorTypeAndAddTraceback(err)
>
> (with a better name, obviously, but that's not the point)

We could just call it "Wrap".

> For the record, I still find the API of errgo to be baffling without a long
> ramp up period. Having both an underlying error and a cause is hard to wrap
> my head around.  I finally managed to load it all up out of long term
> storage, so I get it again... but it's not a terribly easy package to
> understand, in my opinion.

I think this is a valid criticism. I agree that having two entirely
orthogonal errors is awkward (and Tim's struggles with producing
an intuitive error message demonstrate that).

I have been toying with the idea of always maintaining a single
error stack, but noting the cause by keeping track of its depth in the
stack.

So to change the cause, you push an error on the stack that has
a cause-depth of zero. If you don't need to change the cause,
you push an error that has a cause-depth of one more than the
cause-depth of the current top-of-stack.

To extract or check the cause, you traverse cause-depth
levels down the stack and return the error found there.
(To make this more efficient, you could store
the cause at each level)

That means that the cause can be annotated by simply emphasising
(with an asterisk or whatever) the error in the stack that's the current
cause.

The API could remain largely the same, with the exception that
WithCausef would go. We'd probably unexport the Underlying_ and
Cause_ fields from the Err struct type too.

I think I quite like this idea - what do you think?



More information about the Juju-dev mailing list