How to include an error field in gRPC protobuf message using go-grpc

300 views Asked by At

I have a gRPC service written with Go that plays a proxy-like role by wrapping a gRPC message it receives into another gRPC message to a separate backend service. That backend service can return errors but I don't want to simply return an error type from the backend to the proxy service because I'm using a stream and I don't want to abort the whole stream because of a single error.

Instead, what I want to do is return a response message that contains an error field. I am currently just using a string field like this and setting the string ProxiedMessage.err field via fmt.Sprintf("Error encountered: %v", err):

message ProxiedMessage {
  bytes wrappedRpc = 1;
  string err = 2;
}

This works for me but I am wondering if there is a "proper" way to return an error type as a field that I should be using instead. Something like this (which doesn't work):

message ProxiedMessage {
  bytes wrappedRpc = 1;
  error err = 2;
}
3

There are 3 answers

0
blackgreen On

I'd simply define an error message with whatever fields make sense to you, e.g.:

message StreamError {
     int32 code = 1;
     string cause = 2;
}

And then include that as field in the stream message:

message ProxiedMessage {
  bytes wrappedRpc = 1;
  StreamError err = 2;
}

You can also use a simple enum for that, in case you don't need rich error messages. And then you map the error code represented by the enum to some human-readable string on the client side:

enum StreamError {
    Unknown = 0;
    NotFound = 1;
    NotEnoughCoffee = 2;
    ... 
}

message ProxiedMessage {
  bytes wrappedRpc = 1;
  StreamError code = 2;
}
0
Zach On

Within the gRPC-Go codebase you can use our status package alongside error codes (example here: https://github.com/grpc/grpc-go/blob/master/xds/server.go#L364). However, this is not technically part of a proto response message, and represents an RPC failure (err object returned to client). For the proto representation of a status, you can use google.rpc.status defined here: https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto.

0
Aravind On

Afaik this is the commonly used pattern

message Response {
    Error error = ;

}
message Error {
string errorcode = 1;
string errormessage = 2;

}

In the pb file it will look something like this,

type Error struct {
    Code                 string   `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
    Message              string   `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

Using this method errors can be easily handled in server side as well