ghostinecatnewyear
ghostinecatnewyear

Reputation: 301

panic: errors: *target must be interface or implement error in Go

I am making a json unmarshalling error handling function in Go:

import "github.com/pkg/errors"

func parseJSONError(err error) {
    var uterr json.UnmarshalTypeError

    if errors.As(err, &uterr) {
        //...
        return
    }

    var serr json.SyntaxError

    if errors.As(err, &serr) {
        //...
        return
    }
}

But there is a panic in errors.As(): panic: errors: *target must be interface or implement error.

What is target we can learn from the github.com/pkg/errors documentation:

func As(err error, target interface{}) bool

The problem is that both json.UnmarshalTypeError and json.SyntaxError actually implement the error interface. We can learn it from the encoding/json documentation. So I do not have any idea what I am doing wrong. Even explicit casting uterr and serr to the interface{} does not save the situation.

The panic occurs in both github.com/pkg/errors and standard errors packages.

Upvotes: 7

Views: 6441

Answers (2)

David SHainidze
David SHainidze

Reputation: 237

You also can simply add -unsafeptr flag. Like so:

go vet -unsafeptr ./...

Upvotes: -1

blackgreen
blackgreen

Reputation: 44697

The documentation of errors.As states:

As will panic if target is not a non-nil pointer to either a type that implements error, or to any interface type. As returns false if err is nil.

So you have to consider the following:

  1. json.UnmarshalTypeError does not implement error.
  2. *json.UnmarshalTypeError does, because the method Error() string has a pointer receiver (docs)
  3. based on the documentation, errors.As wants a pointer to what implements error, so you need **json.UnmarshalTypeError

Change the code to:

uterr := &json.UnmarshalTypeError{}
if errors.As(err, &uterr) {
    // ...
    return
}

Upvotes: 24

Related Questions