fix: restore the merrs tag on dangling-object deletion audit records

joinErrs ranged over its own empty accumulator string instead of the
errs slice, so the loop body never executed and the function
unconditionally returned "". Its only caller feeds the merrs tag of the
DeleteDanglingObject audit event, so every dangling deletion was
recorded without the per-drive metadata errors: the record showed what
was deleted but not which drives errored or why quorum was lost.

Range over errs instead. The existing separator logic is already right
once the loop runs, since a leading nil error appends "<nil>" and every
later element gets its comma. Upstream's open minio/minio#21580 fixes
the same bug with a strings.Builder rewrite, not taken here: the
function runs once per dangling deletion over a drive-count-sized
slice, and the one-word change is the entire defect.

Co-authored-by: ChatGPT <noreply@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Feng Ruohang
2026-08-04 14:34:30 +08:00
parent 0c14d81510
commit 9dd1dc172d
2 changed files with 22 additions and 1 deletions
+1 -1
View File
@@ -469,7 +469,7 @@ func auditDanglingObjectDeletion(ctx context.Context, bucket, object, versionID
func joinErrs(errs []error) string { func joinErrs(errs []error) string {
var s string var s string
for i := range s { for i := range errs {
if s != "" { if s != "" {
s += "," s += ","
} }
+21
View File
@@ -1281,3 +1281,24 @@ func TestGetObjectWithOutdatedDisks(t *testing.T) {
} }
} }
} }
func TestJoinErrs(t *testing.T) {
errA := errors.New("disk not found")
errB := errors.New("file corrupt")
testCases := []struct {
errs []error
expected string
}{
{nil, ""},
{[]error{}, ""},
{[]error{nil}, "<nil>"},
{[]error{errA}, "disk not found"},
{[]error{nil, errA}, "<nil>,disk not found"},
{[]error{errA, nil, errB, nil}, "disk not found,<nil>,file corrupt,<nil>"},
}
for i, testCase := range testCases {
if got := joinErrs(testCase.errs); got != testCase.expected {
t.Errorf("Test %d: expected %q, got %q", i+1, testCase.expected, got)
}
}
}