8000 SA4023: Triggered by all functions that return a non-nil interface, not just typed nils · Issue #1737 · dominikh/go-tools · GitHub
[go: up one dir, main page]

Skip to content

SA4023: Triggered by all functions that return a non-nil interface, not just typed nils #1737

Closed

Description

@lstoll

Simple example:

package main

import (
	"errors"
	"log"
)

func f1() error {
	return errors.New("error")
}

func main() {
	if err := f1(); err != nil {
		log.Fatal(err)
	}
}

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.

Activity

  1. dominikh commented on Aug 20, 2026

    @dominikh
    Owner

    Is this change intentional?

    No, it is not. Will fix.

  2. dominikh commented on Aug 20, 2026

    @dominikh
    Owner

    Fix will be in the next release (which is due later today or tomorrow).

  3. added a commit that references this issue on Aug 20, 2026
    7dc2d7d
  4. added a commit that references this issue on Aug 21, 2026
    5bb0735
  5. cfergeau commented on Aug 24, 2026

    @cfergeau

    I’m still seeing the false positive from #1738 with latest master commit (f2e7b72a56d)

  6. lstoll commented on Aug 24, 2026

    @lstoll
    Author

    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)
    	}
    }
    
  7. dominikh commented on Aug 24, 2026

    @dominikh
    Owner

    Thank you for digging into this. This should be fixed for good now on master, via 95a3dea.

  8. added a commit that references this issue on Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0