Nil Interface vs Nil Concrete Type
unexpected: err != nil is true even though the underlying value is nilQuick 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
Identify the typed nil return
Find functions returning an interface type where a nil pointer of a concrete type is returned.
- 2
Return nil directly
Replace return nilPointer with return nil to ensure the interface itself is nil.
- 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