A gRPC call can fail instead of returning an OK response. Its error supplies a status code and may include a message. Clients use that information to decide what happened and what to do next; a message without a code can leave that decision ambiguous. section 5.3 section 6.2
Return errors that distinguish the conditions clients need to handle. The gRPC status package supports customized errors that a client can convert and inspect. For example, an order-limit response with a ResourceExhausted code can prompt a later retry rather than an undifferentiated failure. section 6.2 section 6.4
Listing 6.7 Server-client validation
...
import “google.golang.org/grpc/status"
func (s *server) Create(ctx context.Context, in *order.CreateOrderRequest)
(*order.CreateOrderResponse, error) {
var validationErrors []*errdetails.BadRequest_FieldViolation
if in.UserId < 1 { #1
validationErrors = append(validationErrors,
&errdetails.BadRequest_FieldViolation{
Field: "user_id",
Description: "user id cannot be less than 1",
}) #2
}
if in.ProductId < 0 { #3
validationErrors = append(validationErrors,
&errdetails.BadRequest_FieldViolation{
Field: "product_id",
Description: "product id cannot be negative",
}) #4
}
if len(validationErrors) > 0 {
stat := status.New(400, "invalid order request")
badRequest := &errdetails.BadRequest{} #5
badRequest.FieldViolations = validationErrors #6
s, _ := stat.WithDetails(badRequest) #7
return nil, s.Err()
}
return &order.CreateOrderResponse{OrderId: 1243}, nil
}
...
The Order service checks a Create request and records field violations for an invalid user ID or product ID. section 6.2.2
...
import “google.golang.org/grpc/status"
orderResponse, errCreate := orderClient.Create(context.Background(),
&order.CreateOrderRequest{
UserId: -1,
ProductId: 0,
Price: 2,
})
if errCreate != nil {
stat := status.Convert(errCreate) #1
for _, detail := range stat.Details() {
switch errType := detail.(type) { #2
case *errdetails.BadRequest:
for _, violation := range errType.GetFieldViolations() {
log.Printf("The field %s has invalid value. desc: %v",
violation.GetField(), violation.GetDescription())
}
}
}
} else {
log.Printf("Order %d is created successfully.",
orderResponse.OrderId)
}
...
The client converts a failed Create call with status.Convert, inspects BadRequest details, and reads each field violation. section 6.2.2
Let the error inform resilience decisions, but bound the response. Retries can wait on a dependent service and add load while it remains unavailable. A context timeout or deadline limits blocking; a circuit breaker pauses requests after a failure limit and tries again later. Status codes and extended details help clients choose when to retry or change circuit state. section 6.4 section 6.2.2




