From 9dd1dc172d2c89e40d508f21a8554623504f0c45 Mon Sep 17 00:00:00 2001 From: Feng Ruohang Date: Tue, 4 Aug 2026 14:34:30 +0800 Subject: [PATCH] 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 "" 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 Co-authored-by: Claude --- cmd/erasure-object.go | 2 +- cmd/erasure-object_test.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index 78fbe6f09..0247822e7 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -469,7 +469,7 @@ func auditDanglingObjectDeletion(ctx context.Context, bucket, object, versionID func joinErrs(errs []error) string { var s string - for i := range s { + for i := range errs { if s != "" { s += "," } diff --git a/cmd/erasure-object_test.go b/cmd/erasure-object_test.go index 03f452f53..14a30d3bb 100644 --- a/cmd/erasure-object_test.go +++ b/cmd/erasure-object_test.go @@ -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}, ""}, + {[]error{errA}, "disk not found"}, + {[]error{nil, errA}, ",disk not found"}, + {[]error{errA, nil, errB, nil}, "disk not found,,file corrupt,"}, + } + 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) + } + } +}