Nil Interface vs Nil Concrete Type

unexpected: err != nil is true even though the underlying value is nil

Quick Answer

An interface is nil only when both its type and value are nil. Wrapping a nil pointer in an interface creates a non-nil interface. Return nil directly instead of a typed nil pointer.

Why This Happens

Go interfaces have two components: a type descriptor and a value. An interface is nil only when both are nil. If you return a nil pointer of a concrete type, the interface has a non-nil type descriptor, so it is not equal to nil. This is one of the most confusing aspects of Go.

The Problem

type MyError struct {
    Message string
}

func (e *MyError) Error() string { return e.Message }

func validate() error {
    var err *MyError = nil
    return err // returns non-nil interface!
}

func main() {
    if err := validate(); err != nil {
        fmt.Println("got error:", err) // this executes!
    }
}

The Fix

func validate() error {
    // return nil directly, not a typed nil pointer
    return nil
}

func main() {
    if err := validate(); err != nil {
        fmt.Println("got error:", err)
    }
}

Step-by-Step Fix

  1. 1

    Identify the typed nil return

    Find functions returning an interface type where a nil pointer of a concrete type is returned.

  2. 2

    Return nil directly

    Replace return nilPointer with return nil to ensure the interface itself is nil.

  3. 3

    Use reflect for debugging

    Use reflect.ValueOf(err).IsNil() if you need to check if the underlying value is nil.

Bugsly catches this automatically

Bugsly's AI analyzes this error pattern in real-time, explains what went wrong in plain English, and suggests the exact fix — before your users even report it.

Try Bugsly free