diff --git a/fields.go b/fields.go index 5d64911..f500c80 100644 --- a/fields.go +++ b/fields.go @@ -128,6 +128,13 @@ func (c *fields) Is(target error) bool { return ok } +// Cause returns the wrapped error which was the original +// cause of the issue. We only support this because some code +// depends on github.com/pkg/errors.Cause() returning the cause +// of the error. +// deprecated use error.Is() or error.As() instead +func (c *fields) Cause() error { return c.wrapped } + func (c *fields) Error() string { if c.msg == NoMsg { return c.wrapped.Error() diff --git a/fields_test.go b/fields_test.go index 069c02c..47bc3eb 100644 --- a/fields_test.go +++ b/fields_test.go @@ -248,3 +248,9 @@ func TestFieldsStack(t *testing.T) { assert.Equal(t, "value1", m["key1"]) assert.Equal(t, io.EOF.Error(), err.Error()) } + +// Ensure errors.Fields returns an error that is compatible with `github.com/pkf/errors.Cause()` +func TestFieldsCause(t *testing.T) { + err := errors.Fields{"key1": "value1"}.Wrap(io.EOF, "message") + assert.Equal(t, io.EOF, pkgErrorCause(err)) +} diff --git a/stack.go b/stack.go index bb467c3..69b01ec 100644 --- a/stack.go +++ b/stack.go @@ -32,6 +32,13 @@ func (w *stack) Is(target error) bool { return ok } +// Cause returns the wrapped error which was the original +// cause of the issue. We only support this because some code +// depends on github.com/pkg/errors.Cause() returning the cause +// of the error. +// deprecated use error.Is() or error.As() instead +func (w *stack) Cause() error { return w.error } + func (w *stack) HasFields() map[string]any { if child, ok := w.error.(HasFields); ok { return child.HasFields() diff --git a/stack_test.go b/stack_test.go index 7a2daac..04e094c 100644 --- a/stack_test.go +++ b/stack_test.go @@ -144,3 +144,27 @@ func TestFormatStack(t *testing.T) { }) } } + +// Ensure errors.Stack() returns an that works with `github.com/pkf/errors.Cause()` +func TestStackCause(t *testing.T) { + err := errors.Stack(io.EOF) + assert.Equal(t, io.EOF, pkgErrorCause(err)) +} + +// pkgErrorCause is identical to github.com/pkg/errors.Cause() +// Much of our existing code uses that function and depends +// on our errors conforming to the old style Causer interface. +func pkgErrorCause(err error) error { + type causer interface { + Cause() error + } + + for err != nil { + cause, ok := err.(causer) + if !ok { + break + } + err = cause.Cause() + } + return err +} diff --git a/wrap.go b/wrap.go index 21c678a..d3069dd 100644 --- a/wrap.go +++ b/wrap.go @@ -58,6 +58,13 @@ func (e *wrappedError) Is(target error) bool { return ok } +// Cause returns the wrapped error which was the original +// cause of the issue. We only support this because some code +// depends on github.com/pkg/errors.Cause() returning the cause +// of the error. +// deprecated use error.Is() or error.As() instead +func (e *wrappedError) Cause() error { return e.wrapped } + func (e *wrappedError) Error() string { if e.msg == NoMsg { return e.wrapped.Error() diff --git a/wrap_test.go b/wrap_test.go index 206f5d0..65e9dbc 100644 --- a/wrap_test.go +++ b/wrap_test.go @@ -133,3 +133,9 @@ func TestCause(t *testing.T) { assert.Equal(t, "error: wrap 1: wrap 2: the cause", err.Error()) assert.Equal(t, "the cause", cause.Error()) } + +// Ensure errors.wrappedError returns an error that is compatible with `github.com/pkf/errors.Cause()` +func TestWrappedCause(t *testing.T) { + err := errors.Wrap(io.EOF, "message") + assert.Equal(t, io.EOF, pkgErrorCause(err)) +}