Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/20250807151301.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:sparkles: `commonerrors` Add ErrFailed to be used as a generic error where an error is an expected and valid state that should be distinguished from a system error
14 changes: 11 additions & 3 deletions utils/commonerrors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ var (
ErrEOF = errors.New("end of file")
ErrMalicious = errors.New("suspected malicious intent")
ErrOutOfRange = errors.New("out of range")
// ErrFailed should be used as a generic error where an error is an expected and valid state.
// For example a failing command may cause subproccess.Execute to return an error if the command exits with 1 but
// this wouldn't be a system error and you might want to distinguish between this and the subprocess wrapper erroring
// when you pass the message up the stack.
ErrFailed = errors.New("failed")
// ErrWarning is a generic error that can be used when an error should be raised but it shouldn't necessary be
// passed up the chain, for example in cases where an error should be logged but the program should continue. In
// these situations it should be handled immediately and then ignored/set to nil.
Expand All @@ -57,7 +62,7 @@ var warningStrPrepend = fmt.Sprintf("%v: ", warningStr)

// IsCommonError returns whether an error is a commonerror
func IsCommonError(target error) bool {
return Any(target, ErrNotImplemented, ErrNoExtension, ErrNoLogger, ErrNoLoggerSource, ErrNoLogSource, ErrUndefined, ErrInvalidDestination, ErrTimeout, ErrLocked, ErrStaleLock, ErrExists, ErrNotFound, ErrUnsupported, ErrUnavailable, ErrWrongUser, ErrUnauthorised, ErrUnknown, ErrInvalid, ErrConflict, ErrMarshalling, ErrCancelled, ErrEmpty, ErrUnexpected, ErrTooLarge, ErrForbidden, ErrCondition, ErrEOF, ErrMalicious, ErrWarning, ErrOutOfRange)
return Any(target, ErrNotImplemented, ErrNoExtension, ErrNoLogger, ErrNoLoggerSource, ErrNoLogSource, ErrUndefined, ErrInvalidDestination, ErrTimeout, ErrLocked, ErrStaleLock, ErrExists, ErrNotFound, ErrUnsupported, ErrUnavailable, ErrWrongUser, ErrUnauthorised, ErrUnknown, ErrInvalid, ErrConflict, ErrMarshalling, ErrCancelled, ErrEmpty, ErrUnexpected, ErrTooLarge, ErrForbidden, ErrCondition, ErrEOF, ErrMalicious, ErrWarning, ErrOutOfRange, ErrFailed)
}

// Any determines whether the target error is of the same type as any of the errors `err`
Expand Down Expand Up @@ -183,6 +188,8 @@ func deserialiseCommonError(errStr string) (bool, error) {
return true, ErrWarning
case CorrespondTo(ErrOutOfRange, errStr):
return true, ErrOutOfRange
case CorrespondTo(ErrFailed, errStr):
return true, ErrFailed
}
return false, ErrUnknown
}
Expand Down Expand Up @@ -302,7 +309,7 @@ func WrapError(targetError, originalError error, msg string) error {
tErr = ErrUnknown
}
origErr := ConvertContextError(originalError)
if Any(origErr, ErrTimeout, ErrCancelled) {
if Any(origErr, ErrTimeout, ErrCancelled, ErrWarning, ErrFailed) {
tErr = origErr
}
if originalError == nil {
Expand All @@ -312,7 +319,8 @@ func WrapError(targetError, originalError error, msg string) error {
if cleansedMsg == "" {
return New(tErr, originalError.Error())
} else {
return Errorf(tErr, "%v%v %v", cleansedMsg, string(TypeReasonErrorSeparator), originalError.Error())
return Errorf(
tErr, "%v%v %v", cleansedMsg, string(TypeReasonErrorSeparator), originalError.Error())
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions utils/commonerrors/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func TestAny(t *testing.T) {
assert.False(t, Any(nil, ErrInvalid, ErrUnknown))
assert.True(t, Any(fmt.Errorf("an error %w", ErrNotImplemented), ErrInvalid, ErrNotImplemented, ErrUnknown))
assert.False(t, Any(fmt.Errorf("an error %w", ErrNotImplemented), ErrInvalid, ErrUnknown))
assert.True(t, Any(WrapError(ErrUnexpected, WrapError(ErrNotFound, WrapError(ErrFailed, errors.New(faker.Sentence()), "failure!!!"), faker.Sentence()), faker.Sentence()), ErrFailed))
assert.False(t, Any(WrapError(ErrUnexpected, WrapError(ErrNotFound, WrapError(ErrFailed, errors.New(faker.Sentence()), "failure!!!"), faker.Sentence()), faker.Sentence()), ErrUnexpected, ErrNotFound))
}

func TestNone(t *testing.T) {
Expand All @@ -38,6 +40,7 @@ func TestNone(t *testing.T) {
assert.False(t, None(nil, nil, ErrInvalid, ErrNotImplemented, ErrUnknown))
assert.False(t, None(fmt.Errorf("an error %w", ErrNotImplemented), ErrInvalid, ErrNotImplemented, ErrUnknown))
assert.True(t, None(fmt.Errorf("an error %w", ErrNotImplemented), ErrInvalid, ErrUnknown))
assert.False(t, None(WrapError(ErrUnexpected, WrapError(ErrNotFound, WrapError(ErrFailed, errors.New(faker.Sentence()), "failure!!!"), faker.Sentence()), faker.Sentence()), ErrFailed, ErrUnauthorised))
}

func TestCorrespondTo(t *testing.T) {
Expand Down Expand Up @@ -112,6 +115,7 @@ func TestIsCommonError(t *testing.T) {
ErrMalicious,
ErrWarning,
ErrOutOfRange,
ErrFailed,
}
for i := range commonErrors {
assert.True(t, IsCommonError(commonErrors[i]))
Expand Down
Loading