How can I check error types of gRPC calls?

2,006 views
Skip to first unread message

cpu...@gmail.com

unread,
May 15, 2021, 7:47:02 AM5/15/21
to golang-nuts
In my local code, I'm using things like

if errors.Is(err, api.ErrMustRetry) { ... }

How would I achieve the same on errors returned by the gRCP interface? I've noticed these are wrapped: 

rpc error: code = Unknown desc = must retry rpc error: code = Unknown desc = must retry

I assume the errors package won't work here as type information is not carried across gRPC: What is the best practice here: unwrap the root error from the RPC result (how) and perform string comparison?

Thanks,
Andreas

Dan Kortschak

unread,
May 15, 2021, 8:12:28 AM5/15/21
to golan...@googlegroups.com
There is the status package which provides tools for examining the gRPC
errors, https://pkg.go.dev/google.golang.org/grpc/status.


Axel Wagner

unread,
May 15, 2021, 8:13:12 AM5/15/21
to cpu...@gmail.com, golang-nuts
Generally, I would argue that the grpc package maintainers should, at some point, support native wrapping of errors.
In the meantime, they are providing this package: https://pkg.go.dev/google.golang.org/grpc/status
It predates (by a long time) the errors.Is APIs, which is why I assume they haven't yet implemented support

--
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 on the web visit https://groups.google.com/d/msgid/golang-nuts/c3053cb0-d739-496d-a804-7f533ba7a6cbn%40googlegroups.com.

cpu...@gmail.com

unread,
May 18, 2021, 9:07:48 AM5/18/21
to golang-nuts

Thank you for the pointer. After looking at the API, I'm still confused how to use it. I can status.Convert(err) to get a status object but couldn't really figure how how to use that to extract the actual underlying base error?

Brian Candler

unread,
May 18, 2021, 10:16:13 AM5/18/21
to golang-nuts
It's an alias for this:
https://pkg.go.dev/google.golang.org/grpc/internal/status#Status
So it should have Code() and Detail() methods.

Axel Wagner

unread,
May 18, 2021, 10:45:25 AM5/18/21
to cpu...@gmail.com, golang-nuts
You cant to use status.Code(err), which gives you the gRPC status code.


--
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.

Axel Wagner

unread,
May 18, 2021, 10:45:34 AM5/18/21
to cpu...@gmail.com, golang-nuts
*want, sorry, typo :)

burak serdar

unread,
May 19, 2021, 7:38:05 AM5/19/21
to Axel Wagner, cpu...@gmail.com, golang-nuts
Here is something I did to pass custom error information:

Based on the grpc code, if an error type has GRPCStatus()
*status.Status function, then grpc gets the status information using
that method. For the error types that can go through grpc, I have this
method below:

func (e MyError) GRPCStatus() *status.Status {
var code codes.Code
switch e.HTTPStatus {
case http.StatusBadRequest:
code = codes.InvalidArgument
case http.StatusUnauthorized:
code = codes.Unauthenticated
default:
code = codes.Unknown
}
x, _ := json.Marshal(e)
return status.New(code, string(x))
}


In this example, the error type includes an HTTP status code, and the
grpc status is decided based on that. The grpc error contains a JSON
marshaled error information.

On the receiving end, I have this function:

func FromGRPCError(err error) (MyError, bool) {
if x, ok := status.FromError(err); ok {
var e MyError
if json.Unmarshal([]byte(x.Message()), &e) == nil {
return e, true
}
}
return MyError{}, false
}

This decodes the error information from the incoming error.

This scheme can be extended to deal with multiple error types.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfERsv28%2BJV-EVYqhZraHbyYmPftQV6V0i55zVaK1R13HQ%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages