Interface Nil Comparison

ID

go.interface_nil_comparison

Severity

low

Remediation Complexity

moderate

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Go

Tags

CWE:476, error-handling, reliability

Description

Detects the typed-nil interface trap: comparing an interface-typed value — in practice an error — to nil when that value was assigned from a concrete pointer. An interface value holds a (type, value) pair, so once a concrete pointer is stored in it the interface is non-nil even when the underlying pointer is nil, and the familiar err != nil guard then unexpectedly evaluates to true.

Rationale

A nil pointer is not the same as a nil interface. Assigning a typed nil pointer into an error-typed variable boxes it as a non-nil interface carrying the concrete type, so a later if err != nil branch is taken even though no error really occurred. This silently breaks error handling and is one of the most common Go correctness pitfalls.

type myErr struct{}

func (e *myErr) Error() string { return "boom" }

func bad() {
    var p *myErr = nil
    var err error = p   // err holds (*myErr, nil) — a non-nil interface
    if err != nil {     // FLAW — taken even though p is nil
        // ...
    }
}

Remediation

Return a literal nil for the interface (not a typed nil pointer), or convert to the interface only when the pointer is actually non-nil. When a function must surface an error, return nil directly rather than a possibly-nil concrete pointer typed as error.