From 414b5b84026d6741a174d3993de9cd4ea5e279a6 Mon Sep 17 00:00:00 2001 From: Percy Wegmann Date: Fri, 14 Mar 2025 09:02:36 -0500 Subject: [PATCH] util/vizerror: add Wrapf function that combines Errorf with Wrap This makes it convenient to wrap an error with a vizerror that needs to use a format string. Updates tailscale/corp#27066 Signed-off-by: Percy Wegmann --- util/vizerror/vizerror.go | 12 ++++++++++++ util/vizerror/vizerror_test.go | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/util/vizerror/vizerror.go b/util/vizerror/vizerror.go index 919d765d0..f294ef424 100644 --- a/util/vizerror/vizerror.go +++ b/util/vizerror/vizerror.go @@ -75,6 +75,18 @@ func WrapWithMessage(wrapped error, publicMsg string) error { } } +// Wrapf wraps the given error with a Vizerror built using the specified publicMsgFormat and values. +// It always returns a vizerror.Error. +// +// Warning: avoid using an error as one of the format arguments, as this will cause the text +// of that error to be displayed to the end user (which is probably not what you want). +func Wrapf(wrapped error, publicMsgFormat string, a ...any) error { + return Error{ + publicErr: fmt.Errorf(publicMsgFormat, a...), + wrapped: wrapped, + } +} + // As returns the first vizerror.Error in err's chain. func As(err error) (e Error, ok bool) { ok = errors.As(err, &e) diff --git a/util/vizerror/vizerror_test.go b/util/vizerror/vizerror_test.go index 242ca6462..f2538c64c 100644 --- a/util/vizerror/vizerror_test.go +++ b/util/vizerror/vizerror_test.go @@ -64,3 +64,14 @@ func TestWrapWithMessage(t *testing.T) { t.Errorf("Unwrap = %q, want %q", errors.Unwrap(err), wrapped) } } + +func TestWrapf(t *testing.T) { + wrapped := errors.New("wrapped") + err := Wrapf(wrapped, "safe: %s", "for sure") + if err.Error() != "safe: for sure" { + t.Errorf(`Wrapf(wrapped, "safe: for sure").Error() = %q, want %q`, err.Error(), "safe: for sure") + } + if errors.Unwrap(err) != wrapped { + t.Errorf("Unwrap = %q, want %q", errors.Unwrap(err), wrapped) + } +}