Regarding the "var _ error" bit - why not just look at the Error method to see whether it is on a T or a *T? I haven't done a survey about it or anything, but if I need to know whether to pass a T or a *T I often check that type's methods.
On Friday, August 15, 2025 at 5:10:42 AM UTC-6 Oliver Eikemeier wrote: > Static Analysis for Go Error Type Consistency: errortype Linter > > I've been investigating a class of subtle bugs in Go error handling > related to pointer vs. value semantics with errors.As, and developed a > static analysis tool to detect these issues. I'm seeking feedback from the > community on both the approach and the tool's effectiveness. > Problem Statement > > Consider this code attempting to handle AES key size errors: > > key := []byte("My kung fu is better than yours") > _, err := aes.NewCipher(key) > > var kse *aes.KeySizeError > if errors.As(err, &kse) { > fmt.Printf("AES keys must be 16, 24 or 32 bytes long, got %d > bytes.\n", kse) > } else if err != nil { > fmt.Println(err) > } > > The bug: aes.NewCipher returns aes.KeySizeError as a value, but the code > checks for a pointer to *aes.KeySizeError. This type mismatch causes > errors.As to fail silently, with no compile-time detection. > Analysis and Solution Approach > > The core issue is that Go's error interface allows both pointer and value > types to implement error, but the dynamic type matching in errors.As requires > exact type correspondence. This creates opportunities for silent failures > when the expected and actual types don't align. > > I propose a two-part mitigation strategy: > 1. Compile-time Intent Declaration > > Explicit compile-time assertions to document intended usage patterns: > > // MyValueError is intended to be used as a valuevar _ error = MyValueError{} > // MyPointerError is intended to be used as a pointervar _ error = > (*MyPointerError)(nil) > > 2. Static Analysis Tool > > I've developed errortype, a static analyzer that detects inconsistencies > between intended error type usage and actual usage patterns. The tool > analyzes: > > - Function return value types > - Type assertions and type switches > - errors.As target parameters > - Method receiver consistency patterns > > *Example diagnostic output:* > > main.go:14:20: Target for value error "crypto/aes.KeySizeError" is a > pointer-to-pointer, use a pointer to a value instead: "var kse > aes.KeySizeError; ... errors.As(err, &kse)". (et:err) > > Request for Feedback > > I'm particularly interested in feedback on a few points: > > 1. > > *Prevalence*: Have you encountered this pointer/value ambiguity with > error types? How common do you think this class of bug is in practice? > 2. > > *Solution Approach*: What are your thoughts on using var _ error = ... > assertions > to declare an error type's intended usage? Is this a practical convention > to adopt? > 3. > > *Tooling*: The detection heuristics are based on these assertions and > usage pattern analysis. I would be grateful for any real-world testing on > your codebases to validate their effectiveness and performance. > > The tool is currently CLI-only while I refine the detection logic based on > real-world usage patterns. Integration is planned in a later phase. > References > > - *Detailed analysis*: https://blog.fillmore-labs.com/posts/errors-1/ > - *Tool repository*: https://github.com/fillmore-labs/errortype > - *Playground example*: https://go.dev/play/p/m4SEPqkZ2Zu > > I welcome any insights, particularly from those who have encountered > similar issues or have thoughts on static analysis approaches for Go error > handling patterns. > > Best regards, Oliver > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/50b86330-9ac8-41da-9dea-e86a6e3f23e5n%40googlegroups.com.