In Go, the error type is a built-in interface that requires a single method:
type error interface {
Error() string
}
When you create a custom type to represent errors, you must implement this Error() method to satisfy the interface. Without it, your
type cannot be used as an error, leading to compilation errors or runtime panics.
A common mistake when implementing the Error() method is calling formatting functions like fmt.Sprint(),
fmt.Sprintf(), or fmt.Print() directly on the receiver. This creates an infinite loop because these formatting functions
automatically call the Error() method when they encounter a type that implements the error interface.
Here’s what happens in the infinite loop:
- Your
Error() method calls fmt.Sprint(e)
-
fmt.Sprint() sees that e implements the error interface
-
fmt.Sprint() calls e.Error() to get the string representation
- This calls your
Error() method again, creating an endless cycle
This infinite recursion will cause a stack overflow and crash your program.
What is the potential impact?
Missing or incorrectly implemented Error() methods can cause:
- Compilation failures when trying to use the custom type as an error
- Runtime panics due to stack overflow from infinite recursion
- Application crashes that are difficult to debug
- Poor error handling that makes troubleshooting harder for users and developers