Skip to content
This repository was archived by the owner on Dec 1, 2021. It is now read-only.

Unwrap doesn't return the base error #223

Open
yaziine opened this issue Feb 13, 2020 · 7 comments
Open

Unwrap doesn't return the base error #223

yaziine opened this issue Feb 13, 2020 · 7 comments

Comments

@yaziine
Copy link

yaziine commented Feb 13, 2020

Wrapping an error with errors.Wrap, unwrapping it with errors.Unwrap returns the whole error and not the base one. Is it intentional?

https://play.golang.org/p/baYpfrrvN35

@davecheney
Copy link
Member

errors.Unwraps only unwraps errors wrapper with errors.Wrap, not fmt.Errorf

@yaziine
Copy link
Author

yaziine commented Feb 17, 2020

Not sure to understand you here.
Do you mean that errors.Unwraps only unwraps errors wrapped with fmt.Errorf instead?

@davecheney
Copy link
Member

davecheney commented Feb 17, 2020

Unwrap is just a wrapper around the stdlib errors package's Unwrap.

https://github.com/pkg/errors/blob/master/go113.go

@aperezg
Copy link
Member

aperezg commented Feb 17, 2020

As @davecheney said the behaviour of the Unwrap in the pkg/errors is the same that the standard library:

https://play.golang.org/p/73xe4gnoXKz

@puellanivis
Copy link

Oh, this might be the source of the confusion: Wrap(…) returns a &withStack{ &withMessage{ … } } and so when one calls Unwrap() on it, one gets the &withMessage{ … } rather than the original message that was put into Wrap(…), which makes it appear like it is not unwrapping, unless you’re printing stack traces: https://play.golang.org/p/x0JN-W_FStu

This ends up being misleading because one would naturally expect err2 := errors.Unwrap(errors.Wrap(err1)) would result in err2 == err1 but it does not, because internally errors.Wrap is actually double wrapping. No one noticed when using Cause(…) because it kept unwrapping until it got to a non-Causer, but errors.Unwrap only unwraps a single layer. 😕

@zhangguanzhang
Copy link

should use errors.Cause(err)
https://play.golang.org/p/L-uJU07lCAu

@puellanivis
Copy link

errors.Cause will repeatedly unwrap all of the pkg/errors wrappings. So we get:

err := stdErrors.New("thing")
err2 := errors.WithMessage(err, "inner wrap")
err3 := errors.Wrap(err, "outer wrap")
cause := errors.Cause(err3)
unwrap := errors.Unwrap(err3)
// (cause == err) == true
// (unwrap != err3 && unwrap != err2 && unwrap != err) == true

There is no way in this scenario to retrieve err2 from err3, and that’s not ideal.

# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants