Error handling with grpc-java and grpc Status class vs protobuf Status message

5,300 views
Skip to first unread message

steinho...@gmail.com

unread,
May 5, 2016, 12:58:11 PM5/5/16
to grpc.io

Hi,

I try to build a small system using grpc-java and protobuf, with a few services and rpc calls.

For most of the calls, I need to propagate error information from server to client in case something goes wrong.

The documentation at http://www.grpc.io/docs/guides/error.html seems to be lacking some information :-)

Issue 681 (https://github.com/grpc/grpc-java/issues/681 - Attaching Metadata to error Status responses) seems to discuss this and it looks like the general conclusion is to make use of the StatusXXXExceptions on server side. In the yet-to-be-developed version of StatusXXXException, I could set arbitrary metadata on a StatusXXXException which the gRPC runtime would put into the response trailer for a RPC call and which could then be converted back into a StatusXXXException on the client side.

Until the StatusXXXException is developed, I would have to use custom interceptors like shown in grpc-error-example.

Additionally, there is https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto. After a bit of code digging and reading the doc comments, my understand is that the google.rpc.Status message provides a generalized error model on which the io.grpc.Status implementation is based on.

Contrary to the google.rpc.Status protobuf message, the io.grpc.Status java implementation contains only 'code' and 'message' and leaves out 'details', and includes a java Throwable. Looking at https://github.com/grpc/grpc-java/issues/1715 (Document that Status's cause is not transmitted from server to client), I would assume that the cause field is intended for internal handling on the server-side only.

When I want to make use of the protobuf error details messages, I would have to embed a protobuf Status in my RPC response messages.

Are my assumptions correct?

Cheers
Mario

Eric Anderson

unread,
May 5, 2016, 2:21:29 PM5/5/16
to steinho...@gmail.com, grpc.io
On Thu, May 5, 2016 at 9:58 AM, <steinho...@gmail.com> wrote:

Until the StatusXXXException is developed, I would have to use custom interceptors like shown in grpc-error-example.

The new support should almost certainly be in our next release. It isn't hard to code; the hard part was coming to a decision.

Additionally, there is https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto. After a bit of code digging and reading the doc comments, my understand is that the google.rpc.Status message provides a generalized error model on which the io.grpc.Status implementation is based on.

io.grpc.Status and google.rpc.Status are related, but distinct. They each are derived from a common ancestor error model.

(Document that Status's cause is not transmitted from server to client), I would assume that the cause field is intended for internal handling on the server-side only.

It's more often used on client-side, when a local exception caused the RPC to fail. Since servers don't receive a Status, it doesn't serve much point on server-side (although an interceptor could copy the details into trailing metadata).

When I want to make use of the protobuf error details messages, I would have to embed a protobuf Status in my RPC response messages.

Not really. We would suggest using custom trailing metadata instead. Java is a bit special; all the other languages make it much easier to obtain/specify trailing metadata.

Mario Steinhoff

unread,
May 5, 2016, 2:40:51 PM5/5/16
to Eric Anderson, grpc.io
2016-05-05 20:21 GMT+02:00 Eric Anderson <ej...@google.com>:
> The new support should almost certainly be in our next release. It isn't
> hard to code; the hard part was coming to a decision.

Yes, it does not seem too complex. Do you already know when the next
release will be due?

> io.grpc.Status and google.rpc.Status are related, but distinct. They each
> are derived from a common ancestor error model.

Is the common ancestor error model internal to Google or available somewhere?

> It's more often used on client-side, when a local exception caused the RPC
> to fail. Since servers don't receive a Status, it doesn't serve much point
> on server-side (although an interceptor could copy the details into trailing
> metadata).

Ok. So in the service implementation I would execute my application
code, catch any exceptions and map them to a status code, message and
additional custom error metadata if necessary. On the client, the
Status cause is used to provide error information local to the client,
while errors from the server should be provided via trailer metadata.
Correct?

>> When I want to make use of the protobuf error details messages, I would
>> have to embed a protobuf Status in my RPC response messages.
>
>
> Not really. We would suggest using custom trailing metadata instead. Java is
> a bit special; all the other languages make it much easier to obtain/specify
> trailing metadata.

Custom trailing metadata makes sense for most cases.

What I meant was something like described in the Status examples, e.g.
I have a batch request and want to provide status information for each
processed record in a batch response.

Eric Anderson

unread,
May 5, 2016, 2:57:13 PM5/5/16
to Mario Steinhoff, grpc.io
On Thu, May 5, 2016 at 11:40 AM, Mario Steinhoff <steinho...@gmail.com> wrote:
2016-05-05 20:21 GMT+02:00 Eric Anderson <ej...@google.com>:
> The new support should almost certainly be in our next release. It isn't
> hard to code; the hard part was coming to a decision.

Yes, it does not seem too complex. Do you already know when the next
release will be due?

We're expecting 1 month, maybe 2. We've been trying to do 6 week releases, but the last one did end up being delayed by a month. This next release is semi-likely to be GA, so that may also change when we release a bit.

> io.grpc.Status and google.rpc.Status are related, but distinct. They each
> are derived from a common ancestor error model.

Is the common ancestor error model internal to Google or available somewhere?

It's internal, and both public Statuses make a similar departure from it. I wouldn't expect it to be very useful to you, honestly.

> It's more often used on client-side, when a local exception caused the RPC
> to fail. Since servers don't receive a Status, it doesn't serve much point
> on server-side (although an interceptor could copy the details into trailing
> metadata).

Ok. So in the service implementation I would execute my application
code, catch any exceptions and map them to a status code, message and
additional custom error metadata if necessary.

Yes.

On the client, the
Status cause is used to provide error information local to the client,
while errors from the server should be provided via trailer metadata.
Correct?

Yes. To be clear, the server would still provide a status code and possibly a description. The trailer metadata is for additional, application-specific details.

>> When I want to make use of the protobuf error details messages, I would
>> have to embed a protobuf Status in my RPC response messages.
>
>
> Not really. We would suggest using custom trailing metadata instead. Java is
> a bit special; all the other languages make it much easier to obtain/specify
> trailing metadata.

Custom trailing metadata makes sense for most cases.

What I meant was something like described in the Status examples, e.g.
I have a batch request and want to provide status information for each
processed record in a batch response.

Oh, gotcha. Yeah, google.rpc.Status is well-suited for that task.

Mario Steinhoff

unread,
May 5, 2016, 3:11:19 PM5/5/16
to Eric Anderson, grpc.io
2016-05-05 20:56 GMT+02:00 Eric Anderson <ej...@google.com>:
> We're expecting 1 month, maybe 2. We've been trying to do 6 week releases,
> but the last one did end up being delayed by a month. This next release is
> semi-likely to be GA, so that may also change when we release a bit.

Okay, I'm looking forward to that release.
All in all, the experience of using GRPC was great so far. :)

> It's internal, and both public Statuses make a similar departure from it. I
> wouldn't expect it to be very useful to you, honestly.

Nevermind, the available status models seem very well engineered and
are suitable for my needs.

> Yes. To be clear, the server would still provide a status code and possibly
> a description. The trailer metadata is for additional, application-specific
> details.

Yes, thats what I meant.

Another thing I just noted:

Whats the difference between doing:

responseObserver.onError(new
StatusRuntimeException(io.grpc.Status.NOT_FOUND.withDescription("test
description")));

and

throw new StatusRuntimeException(io.grpc.Status.NOT_FOUND.withDescription("test
description"));

in a rpc method implementation?

Both provoke exactly the same behavior in my client. Is there a reason
why I should pefer one method over the other or are there special
cases when one should be used? Looking at it, throwing a exception
seems the simpler variant.

Eric Anderson

unread,
May 5, 2016, 4:09:51 PM5/5/16
to Mario Steinhoff, grpc.io
On Thu, May 5, 2016 at 12:11 PM, Mario Steinhoff <steinho...@gmail.com> wrote:
Whats the difference between doing:

responseObserver.onError(new
StatusRuntimeException(io.grpc.Status.NOT_FOUND.withDescription("test
description")));

and

throw new StatusRuntimeException(io.grpc.Status.NOT_FOUND.withDescription("test
description"));

in a rpc method implementation?

Throwing the exception will always log. That's us weakly "encouraging" you to call onError(), in part so that there is "only one preferred way" to reporting the error. Calling onError() also mirrors the behavior the client will end up seeing.
Reply all
Reply to author
Forward
0 new messages