This repository was archived by the owner on Nov 10, 2025. It is now read-only.

Description
I wrote some code with a custom error type:
var ErrInvalidConfig = errors.New("invalid configuration")
// invalidConfig type is needed to make any error returned from Validator
// to be ErrInvalidConfig.
type invalidConfig struct {
err error
}
func (e *invalidConfig) Is(target error) bool {
return target == ErrInvalidConfig
}
...
Basically, the idea is to make errors.Is(err, ErrInvalidConfig) to return true for every error which is wrapped in invalidConfig type.
Now, the comparison linter complains:
validator.go:42:9: comparing with == will fail on wrapped errors. Use errors.Is to check for a specific error (errorlint)
return target == ErrInvalidConfig
^
Which is obviously incorrect because
- The argument of
Is method, i.e. target, is not supposed to be unwrapped.
- Using
errors.Is in the above example will result in infinite recursion.
There's a similar code in goland standard library (src/syscall/syscall_unix.go):
func (e Errno) Is(target error) bool {
switch target {
case oserror.ErrPermission:
return e == EACCES || e == EPERM
case oserror.ErrExist:
return e == EEXIST || e == ENOTEMPTY
case oserror.ErrNotExist:
return e == ENOENT
}
return false
}
Note that target is compared with oserror.* directly.