-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Closed as not planned
Closed as not planned
Copy link
Labels
Description
What version of Go are you using (go version
)?
$ go version go version go1.20.4 linux/amd64
Does this issue reproduce with the latest release?
Yes
Description
Consider this code (Playground)
var err error
err = errors.Join(err, errors.New("err1"))
err = errors.Join(err, errors.New("err2"))
err = errors.Join(err, nil)
errs := err.(interface{ Unwrap() []error }).Unwrap()
fmt.Println(len(errs), errs)
// Output:
// 1 [err1
// err2]
This happens because when calling errors.Join
, it does not check if one of the errors is a joinError
already, so it creates a new one every time.
- After
err = errors.Join(err, errors.New("err1"))
,err
is ajoinError
with 1 item inside (and that's expected) - After
err = errors.Join(err, errors.New("err2"))
,err
is ajoinError
in which item 1 is ajoinError
itself, and item 2 is the error. - After
err = errors.Join(err, nil)
,err
is ajoinError
that contains 2joinError
's (and the first one contains ajoinError
itself)
We found this bug while trying to implement a pattern where we collect all errors from a channel. We have N goroutines running in parallel, and we wanted to use this pattern to both collect errors (which could be nil) and wait for all goroutines to complete:
errCh := make(chan error, 3)
errCh<-errors.New("err1")
errCh<-errors.New("err2")
errCh<-nil
var err error
for i := 0; i < 3; i++ {
err = errors.Join(err, <-errCh)
}
In the case above, calling Unwrap() []error
on the result lead to unexpected results because of errors being wrapped multiple times in joinError
objects
gdoctor