Fix dropped notification errors and switch to errors.Join

notify/email.go accumulated multi-recipient errors with
multierror.Append(fmt.Errorf(...)) instead of
multierror.Append(result, ...), so the accumulator was overwritten each
iteration and only the last failing recipient's error survived; earlier
failures were silently dropped. The telegram notifier did it correctly.

Replace hashicorp/go-multierror with the stdlib errors.Join everywhere
it was used (notify/email.go, notify/telegram.go, rest/api/rest_private.go,
store/service/service.go, store/image/image.go and store/engine/bolt.go),
which fixes the bug and drops the direct dependency. It stays indirect
because go-pkgz/lcw/v2 still imports it. A regression test in
email_test.go now sends two failing recipients and asserts both errors
are reported.
This commit is contained in:
Dmitry Verkhoturov
2026-07-11 01:28:31 -05:00
committed by Umputun
parent 6e7820d2b7
commit f8f2becb4b
12 changed files with 51 additions and 57 deletions
+6 -9
View File
@@ -21,7 +21,6 @@ import (
log "github.com/go-pkgz/lgr"
R "github.com/go-pkgz/rest"
"github.com/golang-jwt/jwt/v5"
"github.com/hashicorp/go-multierror"
"github.com/umputun/remark42/backend/app/notify"
"github.com/umputun/remark42/backend/app/rest"
@@ -663,10 +662,8 @@ func (s *private) userAllDataCtrl(w http.ResponseWriter, r *http.Request) {
return e
}
var merr error
merr = multierror.Append(merr, write([]byte(`{"info": `))) // send user prefix
merr = multierror.Append(merr, write(userB)) // send user info
merr = multierror.Append(merr, write([]byte(`, "comments":`))) // send comments prefix
// send user prefix, user info and comments prefix
errs := []error{write([]byte(`{"info": `)), write(userB), write([]byte(`, "comments":`))}
// get comments in 100 in each paginated request
for i := range 100 {
@@ -681,15 +678,15 @@ func (s *private) userAllDataCtrl(w http.ResponseWriter, r *http.Request) {
return
}
merr = multierror.Append(merr, write(b))
errs = append(errs, write(b))
if len(comments) != 100 {
break
}
}
merr = multierror.Append(merr, write([]byte(`}`)))
if merr.(*multierror.Error).ErrorOrNil() != nil {
rest.SendErrorJSON(w, r, http.StatusInternalServerError, merr, "can't write user info", rest.ErrInternal)
errs = append(errs, write([]byte(`}`)))
if err := errors.Join(errs...); err != nil {
rest.SendErrorJSON(w, r, http.StatusInternalServerError, err, "can't write user info", rest.ErrInternal)
return
}
}