Skip to content

proposal: context: context.Cause should return a wrapped error #63759

Open
@mitar

Description

@mitar

(I previously made a comment about this which I am now turning into full proposal.)

I have been following the #51365 issue for some time and was really happy that it landed. But now I tried to finally update code to use the new API and I was a bit surprised by it, primarily that it makes it hard to work with logic which expects that the error is context.Canceled and at the same time be able to retrieve the error at the end.

What I mean is that I have code which 1) obtains the error from the context, then it 2) passes it through by returning the error through a chain of function call returns, and then 3) inspects the error and determines that it is about the context cancellation and wants to obtain the cause for it (e.g., log it).

Now, the tricky thing is that at point 3) I cannot know both if the error is context cancellation and what was the cause. I can do that only at point 1).

Options to me seems to be:

  • At point 1) do errors.Join(ctx.Err(), context.Cause(ctx)), but this is ugly if there was no cause, because context.Cause(ctx) in that case returns the same as ctx.Err()`, so I am joining two same errors. So more logic to combine only if they are different. Also returned error message is ugly.
  • I could use gitlab.com/tozd/go/errors's WrapWith which was made so that one error can be made a cause of another error, without modifying either of them. The error message is nicer, but the logic to check if they are different has still to be added.

I understand that originally ctx.Err could not return an context.Canceled error which would unwrap to the cause error to assure that err == context.Canceled continues to work. But why not make context.Cause return such an error already? So in my view, it would be better if context.Cause returned:

  • Same error as ctx.Err if there is no cause.
  • An error which satisfies both context.Is(context.Canceled) and can be unwrapped to the cause error. This can be done by having a custom Is method on the error.

For context.Cause returned errors we do not have to assure that err == context.Canceled holds.

I am not sure if we can still change context.Cause now? Probably not? But could we then introduce yet another context.CauseError or something, which would return an error with the behavior above? It can probably be made in 3rd party library as well, it is not too long, but I think it would be great to have it in standard library.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Incoming

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions