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.

Got the actual stack trace?

Paste it into our free AI explainer to get the cause and the fix for your specific case — no signup, nothing to install.

Explain my error

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