Go error wrapping and formating

The doc for fmt.Errorf specifies
”If there is more than one %w verb, the returned error will implement an Unwrap method returning an error slice containing all the %w operands in the order they appear in the arguments.”
So I kind of expected that in both snippets below the printed output would be the same. But it is not.
Using Join:
```
err1 := errors.New(“error 1”)
err2 := errors.New(“error 2”)
es1 := errors.Join(err1, err2)
fmt,Println(es1)
// Output:
// error 1
// error 2
```

Using fmt.Errorf:
```
err1 := errors.New(“error 1”)
err2 := errors.New(“error 2”)
es2 := fmt.Errorf(“%w%w”, err1, err2)
// Output:
// error 1error 2
```

Digging a bit i find that es1 if of type *errors.joinError but es2` is of type *fmt.wrapErrors.

My question is if the different formatted output is intentional or maybe a bug ?

In the error package documentation you will find :

“An error e wraps another error if e’s type has one of the methods”
You got different type of error depending of your wrap process (aka error creation).

In your sample es1 is the result of error join and then Go wraped them into that type (*errors.joinError)
the same reasoning for the es2 case wrapper in a new type using fmt. (*fmt.wrapErrors)

For example if you add those lines to your sample code :

const name, id = “bueller”, 17
err := fmt.Errorf(“user %q (id %d) not found”, name, id)
fmt.Println(err)
fmt.Println(reflect.TypeOf(err))
fmt.Println(err.(interface{ Unwrap() error }).Unwrap())

See that type of “err” is “*errors.errorString” and if you apply Unwrap you get an error because err is not contained into another error..

HTH,

Yamil

Hi Yamil, Thanks for your answer.

The question i was posing to myself and the community is, if the printout of the error (fmt.Println) should be the same, independent if errors.join or fmt.Errorf with (%w) is used.
If no one expects the printout to be the same than all is fine.

But if the expectation is, that when you wrap 2 (or more) errors with join or with Errorf the result should be the same, then this might be an issue.

In any case, it is something one needs to be aware of, in a use case where one wants that the wrapped errors are printed each on its own line (the behavior when using join).
If you want to ensure the same with fmt.Errorf this is possible with “%w\n%w” but one needs to be aware of this.

A.

Ah, Ok… sorry i misunderstood your question. :frowning:

According docs if you issue Println, it prints the args using default format. In “es1” the type is an slice, and it prints as an slice. In es2 case, your format the output

And yes, it is expected that output will be different…

Thank you for your help in getting this clear.

The answer to your question is in the docs for errors.Join function:

The error formats as the concatenation of the strings obtained by
calling the Error method of each element of errs, with a newline 
between each string.
1 Like