liveBook · Manning

Error handling

As explained in gRPC Microservices in Go

Error handling is the practice of detecting, representing, and responding to failures during software execution or communication.

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

How gRPC Microservices in Go covers it

How deep it goes
Works through status codes and Go validation-detail parsing, without descending into gRPC protocol internals.
Examples
Uses an Order service Create request with invalid fields and a ResourceExhausted order-limit response.
What it assumes
Assumes service-to-service gRPC calls and builds on an existing Order service and client.
What you can do after
Apply it via Go gRPC status conversion to inspect validation errors and choose a response to service failures.
How it connects
Connects gRPC status codes and error details to retries, timeouts, deadlines, and circuit breakers.

Also explained in

Compare how 5 books explain error handling →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of gRPC Microservices in Go. The section links point to the parts of the book it draws on.