GithubHelp home page GithubHelp logo

Proposal: Optional cause about errors HOT 16 OPEN

pkg avatar pkg commented on July 19, 2024 2
Proposal: Optional cause

from errors.

Comments (16)

davecheney avatar davecheney commented on July 19, 2024 2

from errors.

sheenobu avatar sheenobu commented on July 19, 2024 1

Most important point: This is about errors.Cause working without any surprises. errors.Cause() returning nil when the input is non-nil is a surprise. Neither the code nor the documentation cover this.

Is the bug that the Cause implmentation on myCodedError returns whatever is in its err field without checking it is nil?

Yes.

Could this be solved by changing the contract on the causer interface to specific that Cause should not return nil? I can see the argument for allow Cause to return nil, but i'd like to understand what the use case for this is.

Yes it could be solved by changing the contract of causer. It would be a documentation issue then, correct?

The use case for this is interoping with custom error types which implement causer and whether they'll always return non-nil errors. In some cases this could be a programming mistake and other cases it could be purposeful.

Do we mandate non-nil errors via documentation or a panic? Or treat nil errors from causer as 'this causer has no underlying error, so return it EDIT: it being the causer, not the nil underlying error'.

from errors.

jaekwon avatar jaekwon commented on July 19, 2024 1

Ok, I just ran into this, but what I expected was to be able to do this:

func (err *sdkError) Cause() error {
	if err.cause != nil {
		return err.cause
	}
	return err
}

Sometimes *sdkError has a .cause, sometimes it doesn't -- it's up to the user. And when an error doesn't have another cause to blame, it is the underlying cause. Right? :)

  • If you think Cause means ImmediateCause, then you'd expect the underlying error to return nil on Cause.
  • If you think Cause means UnderlyingCause, then you'd expect to always return the root/underlying error and never nil or any intermediary errors.
  • If you think Cause means BlameCause, then you'd return the immediate cause, or the current error if you couldn't blame another error.

Made a PR (see link) to handle all use-cases (return nil or self as cause).

from errors.

davecheney avatar davecheney commented on July 19, 2024

Is the bug that the Cause implmentation on myCodedError returns whatever is in its err field without checking it is nil?

Could this be solved by changing the contract on the causer interface to specific that Cause should not return nil? I can see the argument for allow Cause to return nil, but i'd like to understand what the use case for this is.

from errors.

tscholl2 avatar tscholl2 commented on July 19, 2024

I just ran into this, and it was a surprise to me. Here is the code I used: https://play.golang.org/p/RYXqML2VAw

Basically, gorilla's securecookie happens to have the same interface, but with different semantics. I did not realize this, and was very confused why it was returning nil.

I love this errors package, and it's never failed me. I guess my two cents would be that if an error is not nil, but it's Cause() returns nil, then errors.Cause should return the original error, if that makes sense. I understand if this goes against your original intention though.

from errors.

tscholl2 avatar tscholl2 commented on July 19, 2024

I agree. That second change is almost exactly what I used in my code right now as a work around. I also think the second way matches semantically with what the docs say (with some liberal interpretation):

Cause returns the underlying cause of the error, if possible.

I guess I'm assuming a non-nil error always has a non-nil cause. But I guess in programming, it often seems like things break for no reason :)

Would you like me to submit a PR with this? I think it might also be good to add a quick sentence in the docs right after the other sentences about the causer interface. Something like: "If Cause() returns nil, the original error is returned". Or maybe a warning about how other packages may have the same cause interface with different semantics?

from errors.

chanxuehong avatar chanxuehong commented on July 19, 2024

is this ok?
https://github.com/chanxuehong/errors/blob/master/func.go#L90

from errors.

tscholl2 avatar tscholl2 commented on July 19, 2024

That looks good to me. If I'm reading it right, a non-nil error always has a non-nil cause, which was my original issue. The only thing I might suggest is adding a sentence to the doc saying this.

from errors.

davecheney avatar davecheney commented on July 19, 2024

from errors.

puellanivis avatar puellanivis commented on July 19, 2024

I don’t think a Cause() should ever be expected to return nil, however, I do suppose it is a possible return value from an implementation, and as such, it should be handled gracefully.

from errors.

jaekwon avatar jaekwon commented on July 19, 2024

@davecheney:

I would appreciate it if you can help me understand, on #89, not this
PR, your use case, and why this change is necessary, and could your
requirement be handled without changing the operation of Cause?

I wrote a bit up there (see sdkError example).

We need sdkError because in the SDK, every such error should also have a numeric code for the type of error. When you create an sdkError, you specify a numeric code and any log information for debugging purposes. Sometimes you'll want to attach an immediate cause for creating the sdkError, but other times there will be no immediate cause. So sdkError.Cause() sometimes needs to return nil/itself, and sometimes another error.

https://github.com/cosmos/cosmos-sdk/blob/62f736fbd047194aaee8cb68d2072ca316eec550/errors/errors.go#L155

Of course it would be sufficient to allow errors.Cause() to handle nil return values from causer.Cause(), but it would also be nice to allow the implementor of causer to return itself as the cause, signifying that it is the underlying cause. It would have been the least surprising behavior for me.

from errors.

davecheney avatar davecheney commented on July 19, 2024

from errors.

jaekwon avatar jaekwon commented on July 19, 2024

I can't use With* to wrap the cause because it needs to be wrapped by sdkError, but I can do the former of having two errors, one that embeds the other and also has a cause field.

Thank you, and looking forward to the results of the survey. LMK if I can help.

from errors.

gregwebs avatar gregwebs commented on July 19, 2024

Can we create a new RootCause function and deprecate the existing Cause function? That will satisfy backwards compatibility. Cause would only be dropped in a breaking release.

from errors.

davecheney avatar davecheney commented on July 19, 2024

Hi Greg,

What would this new RootCause function do?

from errors.

gregwebs avatar gregwebs commented on July 19, 2024

It would just fix this bug.

from errors.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.