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 [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/golang-nuts/50b86330-9ac8-41da-9dea-e86a6e3f23e5n%40googlegroups.com.