You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SA4023: Triggered by all functions that return a non-nil interface, not just typed nils #1737
Using both Go 1.26.7 and Go 1.27.0, with staticcheck v0.7.0, this passes.
On v0.8.0 (and main), this reports:
$ go run honnef.co/go/tools/cmd/staticcheck@1cfedab .
main.go:13:18: this comparison is always true (SA4023)
main.go:13:12: the lhs of the comparison is the 1st return value of this function call
main.go:8:6: satest.f1 never returns a nil interface value
exit status 1
The printed message is correct. However, the documentation indicates that this check is intended for catching typed nil cases, which this is not. The commentary in #845 also seems to confirm that.
Is this change intentional? The typed nil case is dangerous and it is good to check for that, however I think this change makes the check less useful. Having the nil check there does not seem problematic, and removing it risks panics or other issues should the function decide to return a nil error in future.
I looked at some of the code that is still showing a false positive for this, and it seems like the combination of a for loop calling a function that will always return a package error variable/sentinal error triggers this. example:
package main
import (
"errors"
"log"
)
var errSentinal = errors.New("error")
// returning a sentinel error is fine.
func f1() error {
return errSentinal
}
// a function that in a foor loop calls a function that returns a sentinal error
// fails.
func f2() error {
for {
if err := f1(); err != nil {
return err
}
}
}
// returning a call to a function that returns the sentinal is fine though.
func f3() error {
return f1()
}
// returning a non-sentinal error is fine.
func f4() error {
return errors.New("error")
}
// a function that in a foor loop calls a function that returns a normal error
// is fine.
func f5() error {
for {
if err := f4(); err != nil {
return err
}
}
}
func main() {
// this is fine
if err := f1(); err != nil {
log.Fatal(err)
}
// this call reports:
// $ go run honnef.co/go/tools/cmd/staticcheck@f2e7b72 ./...
// main.go:56:18: this comparison is always true (SA4023)
// main.go:56:12: the lhs of the comparison is the 1st return value of this function call
// main.go:17:6: sttest.f2 never returns a nil interface value
// exit status 1
if err := f2(); err != nil {
log.Fatal(err)
}
// this is fine
if err := f3(); err != nil {
log.Fatal(err)
}
// this is fine
if err := f4(); err != nil {
log.Fatal(err)
}
// this is fine
if err := f5(); err != nil {
log.Fatal(err)
}
}
Activity
dominikh commentedon Aug 20, 2026
No, it is not. Will fix.
dominikh commentedon Aug 20, 2026
Fix will be in the next release (which is due later today or tomorrow).
SA4023: only flag possibly typed nils
SA4023: only flag possibly typed nils
cfergeau commentedon Aug 24, 2026
I’m still seeing the false positive from #1738 with latest
mastercommit (f2e7b72a56d)lstoll commentedon Aug 24, 2026
I looked at some of the code that is still showing a false positive for this, and it seems like the combination of a for loop calling a function that will always return a package error variable/sentinal error triggers this. example:
dominikh commentedon Aug 24, 2026
Thank you for digging into this. This should be fixed for good now on master, via 95a3dea.
chore(deps): update all-dependencies
chore(deps): update all-dependencies
chore(deps): update all-dependencies
chore(deps): update all-dependencies