Passing custom proto message using WithDetails() from gRPC status package
Asked Answered
T

2

7

I have been recently experimenting with gRPC error handling and wanted to pass in my own proto message to the client (defining my own error details and internal error codes). After searching around, found out couple of examples that uses WithDetails() in gRPC status package to attach custom metadata. I started implementing the same as follows

gRPC proto message

message ErrorInfo {
    int64 error_code = 1;
    string error_message = 2;
    string resource_name = 3;
}

Server-side implementation

// Frame the error message
        st := status.New(codes.NotFound, "object not found")
        errInfo := &api.ErrorInfo {
            ErrorCode: 100,
            ErrorMessage: "Fetching credential failed",
            ResourceName: req.GetBackupLocation().GetCloudCredential(),
        }
        var err error
        st, err = st.WithDetails(errInfo)
        if err != nil {
            // If this errored, it will always error
            // here, so better panic so we can figure
            // out why than have this silently passing.
            panic(fmt.Sprintf("Unexpected error attaching metadata: %v", err))
        }

        return  st.Err()

Client-side implementation

fmt.Printf("line 76 err :%v", err)
                st := status.Convert(err)
                for _, detail := range st.Details() {
                    switch t := detail.(type) {
                    case *api.ErrorInfo:
                        fmt.Printf("error code: %v", t.GetErrorCode())
                        fmt.Printf("error msg: %v", t.GetErrorMessage())
                        fmt.Printf("resource name: %v", t.GetResourceName())
                    }
                }

When i run the code, it hit the Panic() added in the server code which means WithDetails() errored out.

For proceeding further, removed panic on server side, with this client throws the following error

:any: message type "" isn't linked inerror

Questions:

  • Does WithDetails() only work for googleapis/rpc/errdetails standard gRPC proto definition and not with custom proto?
  • Looking at the proto files and code implementation, I don't see anything specific to gRPC errdetails package.

  • When I tried with the proto message from this package, it's working fine.

[ Note: i am using gogo protobuf]

Can any one please let know what is that i am missing here?

Tybalt answered 20/4, 2020 at 8:19 Comment(5)
What's the error returned by WithDetails?Binny
Surprisingly I am not seeing any error being generated, it's null. Is it something to do with gogo proto? The reason for asking this is proto files generated in errdetails package has additional fields like XXX_ but the ones i generated don't have anything. What does this error message any: message type "" isn't linked inerror mean?Tybalt
That error is probably just a consequence of the server doing weird things. Ignore it until you have the server working. If %v formats as <nil> but the error doesn't actually equal nil it's likely a case of nil interface values. I'd consider this a bug in gogo/protobuf. Try the %T verb instead.Binny
1) I tried %T even that gave nil 2) Secondly while searching on google, i came across a link for grpc status package specifically we use gogo proto. Thought will give it a try and tried this package "github.com/gogo/status" . When i use this, things seem to work. I fully don't understand the package implementation.Tybalt
May this commit https://github.com/gogo/status/commit/d60b5acac426cb52f7e28124c6aaa862d9f339f5 fixes the issues i am facing.Tybalt
R
-1

From my point of view, mixing business logic errors with transport errors should not be considered as a good practice, even if GRPC API allows it. Adding special Result or Error structure to every response (with your own set of fields and codes) is much more clean and flexible way to report about request handling state.

Rowel answered 26/4, 2020 at 21:59 Comment(2)
I don't understand the downvotes. Vitaly have a valid point here. For those who would like more info about this strategy for error handling check out this thread. Engineers at Google don't mix business logic errors with transport errors; they use their pre-defined Error Model which is returned to the client when an API error occurs.Bonheur
Another benefit of not mixing business logic with transport errors is that in case of gRPC streams we want to keep the connection open to respond to other messages that might come through the RPC. Returning an error at transport layer level would terminate/close it.Bonheur
O
-1

I was facing a similar error (any: message type "" isn't linked in *errors.errorString). In my case it was due to grpc.Status API.

If you're using gogo proto you need to import/use

"github.com/gogo/status"

Instead of

"google.golang.org/grpc/status"

Osteotomy answered 14/5, 2020 at 20:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.