go 1.27 vet check breaks errors.Is compatibility?

147 views
Skip to first unread message

Steven Hartland

unread,
Aug 21, 2026, 5:11:12 AM (2 days ago) Aug 21
to golang-nuts
Go 1.27 made stdversion checks run by default when running go test as well as an extra check for errors.Is compatibility. This checks for non-pointer types which appears to break compatibility with existing code, you can see this here

Under go 1.26 the errors.Is works as expected but under 1.27 you get a compile failure.

If I remove the & so it operates on HTTPError and not *HTTPError as I believe is suggested by the vet check two of the tests fail as HTTPError is not comparable.

I even tried with a custom Is function defined, go vet check still fails.

Am I missing something, or is this a significant compatibility breakage introduced by 1.27? 

# [play]
./prog_test.go:27:44: %w wants operand of error type HTTPError, not pointer type *HTTPError (defeats errors.Is)

Go build failed.

=== RUN   TestErrorsIs
=== RUN   TestErrorsIs/wrapped-eof
=== RUN   TestErrorsIs/wrapped-sentinel
    prog_test.go:37: wrapped: &fmt.wrapError{msg:"wrapped eof error: EOF", err:main.HTTPError{error:(*errors.errorString)(0x86ae60), StatusCode:404, Details:[]interface {}{"some extra info"}}} is not sentinel
=== RUN   TestErrorsIs/direct-sentinel
    prog_test.go:42: sentinel: &fmt.wrapError{msg:"wrapped eof error: EOF", err:main.HTTPError{error:(*errors.errorString)(0x86ae60), StatusCode:404, Details:[]interface {}{"some extra info"}}} is not sentinel
--- FAIL: TestErrorsIs (0.00s)
    --- PASS: TestErrorsIs/wrapped-eof (0.00s)
    --- FAIL: TestErrorsIs/wrapped-sentinel (0.00s)
    --- FAIL: TestErrorsIs/direct-sentinel (0.00s)
FAIL

Program exited.

=== RUN   TestErrorsIs
=== RUN   TestErrorsIs/wrapped-eof
=== RUN   TestErrorsIs/wrapped-sentinel
=== RUN   TestErrorsIs/direct-sentinel
--- PASS: TestErrorsIs (0.00s)
    --- PASS: TestErrorsIs/wrapped-eof (0.00s)
    --- PASS: TestErrorsIs/wrapped-sentinel (0.00s)
    --- PASS: TestErrorsIs/direct-sentinel (0.00s)
PASS

Steven Hartland

unread,
Aug 21, 2026, 6:42:59 AM (2 days ago) Aug 21
to golang-nuts
Workaround is to run go test with -vet=off

Jason Phillips

unread,
Aug 22, 2026, 2:29:02 PM (20 hours ago) Aug 22
to golang-nuts
> I even tried with a custom Is function defined, go vet check still fails.
It seems to be the Error function that's significant to the linter here.

The linter is happy once your error type implements the error interface.

Steven Hartland

unread,
Aug 22, 2026, 2:40:34 PM (19 hours ago) Aug 22
to Jason Phillips, golang-nuts
Thanks Jason, it already has an Error method but I guess the linter isn’t checking properly and is missing the embedded error is providing that.

It a nice workaround though 🙂

  Regards
  Steve

--
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...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/b7b31927-f85d-4008-b206-f92e4f6e8c70n%40googlegroups.com.

Sean Liao

unread,
Aug 22, 2026, 3:28:18 PM (19 hours ago) Aug 22
to Steven Hartland, Jason Phillips, golang-nuts
The vet warning is actually because of the embedded / promoted Error
method is found.

Even though you can call .Error() on both HTTError and *HTTPError
(through automatic dereferencing)
HTTPError is not comparable to *HTTPError.
Which is what vet is warning about since it expects the type that
implements the error interface to be the canonical representation of
the error value.

If you instead wanted to implement Is, then you have to make the value
type comparable:
https://go.dev/play/p/A-5rPS6eY_b

- sean
> To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAA38peZ6%2B4qY5jEdeNuk_%2Bre3q45P6pfV_kzft5oADYdD%3DB-QQ%40mail.gmail.com.

Steven Hartland

unread,
Aug 22, 2026, 4:31:39 PM (18 hours ago) Aug 22
to Sean Liao, Jason Phillips, golang-nuts
While that works it's way more overhead than the pointer comparison that's currently needed and would need all constructors and uses to be updated in the code base.
Reply all
Reply to author
Forward
0 new messages