Skip to content

Commit e17500e

Browse files
committed
fix: Unwrap joinErr in gin.Error()
1 parent 61c2b1c commit e17500e

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

errors.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package gin
66

77
import (
8+
"errors"
89
"fmt"
910
"reflect"
1011
"strings"
@@ -165,11 +166,32 @@ func (a errorMsgs) String() string {
165166
return ""
166167
}
167168
var buffer strings.Builder
168-
for i, msg := range a {
169-
fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err)
170-
if msg.Meta != nil {
171-
fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)
169+
count := 1
170+
for _, msg := range a {
171+
for _, err := range unwrapJoinErr(msg.Err) {
172+
fmt.Fprintf(&buffer, "Error #%02d: %s\n", count, err)
173+
if msg.Meta != nil {
174+
fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)
175+
}
176+
count++
172177
}
173178
}
174179
return buffer.String()
175180
}
181+
182+
func unwrapJoinErr(err error) []error {
183+
if err == nil {
184+
return nil
185+
}
186+
var result []error
187+
if multi, ok := err.(interface{ Unwrap() []error }); ok {
188+
for _, e := range multi.Unwrap() {
189+
result = append(result, unwrapJoinErr(e)...)
190+
}
191+
} else if single := errors.Unwrap(err); single != nil {
192+
result = append(result, unwrapJoinErr(single)...)
193+
} else {
194+
result = append(result, err)
195+
}
196+
return result
197+
}

errors_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package gin
77
import (
88
"errors"
99
"fmt"
10+
"strings"
1011
"testing"
1112

1213
"github.com/gin-gonic/gin/internal/json"
@@ -138,3 +139,28 @@ func TestErrorUnwrap(t *testing.T) {
138139
var testErrNonPointer TestErr
139140
require.ErrorAs(t, wrappedErr, &testErrNonPointer)
140141
}
142+
143+
func TestErrorJoinFormatting(t *testing.T) {
144+
// Create a context with errorMsgs slice
145+
c, _ := CreateTestContext(nil)
146+
147+
// Create a joined error
148+
err1 := errors.New("service error")
149+
err2 := errors.New("store error")
150+
joined := errors.Join(err1, err2)
151+
152+
// Add to context errors
153+
c.Error(joined)
154+
155+
// Call String(), which should now unwrap and format both
156+
output := c.Errors.String()
157+
158+
// Check that both individual errors appear separately
159+
if !strings.Contains(output, "Error #01: service error") || !strings.Contains(output, "Error #02: store error") {
160+
t.Errorf("expected unwrapped errors in output, got:\n%s", output)
161+
}
162+
163+
if strings.Contains(output, "service error\nstore error") {
164+
t.Errorf("output contains unexpected joined formatting:\n%s", output)
165+
}
166+
}

0 commit comments

Comments
 (0)