go-errorlint is a source code linter for Go software that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13.
Error wrapping allows for extra context in errors without sacrificing type information about the error's cause.
For details on Go error wrapping, see: https://golang.org/pkg/errors/
go install github.com/polyfloyd/go-errorlint@latest
go-errorlint accepts a set of package names similar to golint:
go-errorlint ./...
If there are one or more results, the exit status is set to 1.
To automatically fix issues where possible, use the -fix flag:
go-errorlint -fix ./...
The tool can automatically fix:
[!CAUTION] These fixes are still under development and the behavior is not yet stable. It is possible that it will make mistakes and cause more harm than good. Use with caution.
%v to %w)err == ErrFoo with errors.Is(err, ErrFoo))err.(*MyError) with errors.As usage)Complex cases like switches on errors or type switches cannot be automatically fixed.
This lint is disabled by default. Use the -errorf flag to toggle.
// bad
fmt.Errorf("oh noes: %v", err)
// ^ non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
// good
fmt.Errorf("oh noes: %w", err)
You can pass -fix to have go-errorlint automatically fix these issues for you.
Caveats:
-errorf lint, keep in mind that any errors wrapped by
fmt.Errorf implicitly become part of your API as according to Hyrum's
Law.fmt.Errorf call which will
break on Go 1.19 and earlier. Pass -errorf-multi=0 to retain backwards compatibility. This
functionality will be passively maintained until at least Go 1.19 has been dropped from official
support.This lint is enabled by default. Use the -comparison flag to toggle.
// bad
err == ErrFoo
// ^ comparing with == will fail on wrapped errors. Use errors.Is to check for a specific error
// bad
switch err {
case ErrFoo:
}
// ^ switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors
// good
errors.Is(err, ErrFoo)
Errors returned from standard library functions that explicitly document that
an unwrapped error is returned are allowed by the linter. Notable cases are
io.EOF and sql.ErrNoRows.
You can pass -fix to have go-errorlint automatically fix these issues for you.
Caveats:
(io.Reader).Read to io.EOF without
errors.Is is considered valid as this is
explicitly documented behaviour.
However, nothing stops 3rd party implementations from still wrapping
io.EOF, causing this linter to not detect such cases.This lint is enabled by default. Use the -asserts flag to toggle.
// bad
myErr, ok := err.(*MyError)
// ^ type assertion on error will fail on wrapped errors. Use errors.As to check for specific errors
// bad
switch err.(type) {
case *MyError:
}
// ^ type switch on error will fail on wrapped errors. Use errors.As to check for specific errors
// good
var me MyError
ok := errors.As(err, &me)
You can pass -fix to have go-errorlint automatically fix these issues for you.
Do you think you have found a bug? Then please report it via the Github issue tracker. Make sure to attach any problematic files that can be used to reproduce the issue. Such files are also used to create regression tests that ensure that your bug will never return.
When submitting pull requests, please prefix your commit messages with fix: or feat: for bug
fixes and new features respectively. This is the
Conventional Commits scheme that is used to
automate some maintenance chores such as generating the changelog and inferring the next version
number.
Go
100.0%
go-errorlint is a source code linter for Go software that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13.
Error wrapping allows for extra context in errors without sacrificing type information about the error's cause.
For details on Go error wrapping, see: https://golang.org/pkg/errors/
go install github.com/polyfloyd/go-errorlint@latest
go-errorlint accepts a set of package names similar to golint:
go-errorlint ./...
If there are one or more results, the exit status is set to 1.
To automatically fix issues where possible, use the -fix flag:
go-errorlint -fix ./...
The tool can automatically fix:
[!CAUTION] These fixes are still under development and the behavior is not yet stable. It is possible that it will make mistakes and cause more harm than good. Use with caution.
%v to %w)err == ErrFoo with errors.Is(err, ErrFoo))err.(*MyError) with errors.As usage)Complex cases like switches on errors or type switches cannot be automatically fixed.
This lint is disabled by default. Use the -errorf flag to toggle.
// bad
fmt.Errorf("oh noes: %v", err)
// ^ non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
// good
fmt.Errorf("oh noes: %w", err)
You can pass -fix to have go-errorlint automatically fix these issues for you.
Caveats:
-errorf lint, keep in mind that any errors wrapped by
fmt.Errorf implicitly become part of your API as according to Hyrum's
Law.fmt.Errorf call which will
break on Go 1.19 and earlier. Pass -errorf-multi=0 to retain backwards compatibility. This
functionality will be passively maintained until at least Go 1.19 has been dropped from official
support.This lint is enabled by default. Use the -comparison flag to toggle.
// bad
err == ErrFoo
// ^ comparing with == will fail on wrapped errors. Use errors.Is to check for a specific error
// bad
switch err {
case ErrFoo:
}
// ^ switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors
// good
errors.Is(err, ErrFoo)
Errors returned from standard library functions that explicitly document that
an unwrapped error is returned are allowed by the linter. Notable cases are
io.EOF and sql.ErrNoRows.
You can pass -fix to have go-errorlint automatically fix these issues for you.
Caveats:
(io.Reader).Read to io.EOF without
errors.Is is considered valid as this is
explicitly documented behaviour.
However, nothing stops 3rd party implementations from still wrapping
io.EOF, causing this linter to not detect such cases.This lint is enabled by default. Use the -asserts flag to toggle.
// bad
myErr, ok := err.(*MyError)
// ^ type assertion on error will fail on wrapped errors. Use errors.As to check for specific errors
// bad
switch err.(type) {
case *MyError:
}
// ^ type switch on error will fail on wrapped errors. Use errors.As to check for specific errors
// good
var me MyError
ok := errors.As(err, &me)
You can pass -fix to have go-errorlint automatically fix these issues for you.
Do you think you have found a bug? Then please report it via the Github issue tracker. Make sure to attach any problematic files that can be used to reproduce the issue. Such files are also used to create regression tests that ensure that your bug will never return.
When submitting pull requests, please prefix your commit messages with fix: or feat: for bug
fixes and new features respectively. This is the
Conventional Commits scheme that is used to
automate some maintenance chores such as generating the changelog and inferring the next version
number.
Go
100.0%