errors icon indicating copy to clipboard operation
errors copied to clipboard

Proposal/Question: Type assertions on the entire error stack

Open sheenobu opened this issue 9 years ago • 8 comments

Originally, checking if a error matches a given interface, you would simply m, ok := err.(myInterface). With pkg/errors, it's now m, ok := errors.Cause(err).(myInterface) (Basing this off of the writing here: http://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully)

However, this falls apart if your error stack has myInterface in the middle, since errors.Cause(err).(myInterface) only checks the bottom of the stack:

err := errors.New("Sample error")
// because myCodedError is in the middle of a stack, we have no way
// of getting at Code without writing a custom function that is a near 
// clone of errors.Cause()
err = &myCodedError{code: 404, err: err}
err = Wrap(err, "Wrapping 1")
err = Wrap(err, "Wrapping 2")
err = Wrap(err, "Wrapping 3")

Question: What is the best way to handle this? Custom functions for each of your interfaces which may get paired with a causer. A generalized function added to pkg/errors?

I've thrown up some code here which shows the varying cases and solutions https://play.golang.org/p/E8eJeWbOuV

sheenobu avatar Oct 23 '16 16:10 sheenobu

errors.Cause always unwraps as far as it can, ie to the bottom of the stack, or at least until you hit an error which does not implement Cause.

What is it you want to do? Do you want to recover &myCodedError? If so, dont' have it implement Cause and it will become the result of errors.Cause?

davecheney avatar Oct 23 '16 22:10 davecheney

errors.Cause always unwraps as far as it can, ie to the bottom of the stack, or at least until you hit an error which does not implement Cause.

That's understood. It's that the stack of errors lose all type information except for the one on the top and the one at the bottom.

What is it you want to do? Do you want to recover &myCodedError? If so, dont' have it implement Cause and it will become the result of errors.Cause?

That is a solution but it becomes a mandate that error types with Cause methods can only have Cause methods.

sheenobu avatar Oct 24 '16 00:10 sheenobu

I am wondering the same thing. Reading through @davecheney article https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully the advice is to use behavior. If the behavior is somewhere in the middle of the stack and that error implements Cause, I currently don't have a way to easily get that via this pkg. I would have to implement my own unwind.

danilobuerger avatar Mar 04 '17 08:03 danilobuerger

@danilobuerger My original post has a generalized but not optimal Recurse method for unwinding. I'm still wavering on a design, though, which wraps both this issue and key-value logging concerns.

sheenobu avatar Mar 04 '17 21:03 sheenobu

Related proposed solution: https://github.com/pkg/errors/issues/144

jaekwon avatar Dec 30 '17 20:12 jaekwon

How would any of you propose to assert the entire wrapped error stack?

Without reflect you cannot pass an interface type for it to be tested again, so each and every attempt to assert against any interface would have to for-loop through the errors.

If you want to task to each person the interface matching on each error in the cause chain… you can already do that, because you can type assert yourself in your own code.

There is no way within the bounds of go lang at this time to do any thing about making this less difficult or arduous an adventure.

puellanivis avatar Dec 30 '17 20:12 puellanivis

@puellanivis

Without reflect you cannot pass an interface type for it to be tested again, so each and every attempt to assert against any interface would have to for-loop through the errors.

Right, that's why #144 suggests making errors.Wrap() error return the same error instead of creating a new one if it's already wrapped. That makes it unnecessary to check the whole chain -- the programmer should know exactly how many times to unwrap, and it's typically just once.

jaekwon avatar Jan 03 '18 12:01 jaekwon

I think this is addressed with standard errors.As.

mitar avatar Nov 30 '21 21:11 mitar