liveBook · Manning

gRPC status package

As explained in gRPC Microservices in Go

The gRPC status package is a Go package that constructs, interprets, and converts RPC status errors containing codes, messages, and optional details.

The Go gRPC status package gives service errors a code and descriptive message instead of leaving callers to interpret an unstructured error string. A caller can use the code to decide what to do next; for example, a ResourceExhausted response may call for a later retry rather than immediate failure. section 5.4 section 6.2

At a service boundary, resolve a downstream error with status.FromError when its code and message are enough. To preserve more context, create a new status with status.New, attach a detail with WithDetails, and return the resulting error. An Order service can mark a Payment failure as a payment field violation while reporting that order creation failed. section 5.3.3 section 5.3.4

func (a Application) PlaceOrder(order domain.Order) (domain.Order, error) {
    err := a.db.Save(&order)
    if err != nil {
        return domain.Order{}, err
    }
    paymentErr := a.payment.Charge(&order)
    if paymentErr != nil {
        st, _ := status.FromError(paymentErr)                             #1
        fieldErr := &errdetails.BadRequest_FieldViolation{
            Field:       "payment",
            Description: st.Message(),
        }                                                                 #2
        badReq := &errdetails.BadRequest{}                                #3
        badReq.FieldViolations = append(badReq.FieldViolations, fieldErr) #4
        orderStatus := status.New(codes.InvalidArgument, "order creation 
         failed")                                                       #5
        statusWithDetails, _ := orderStatus.WithDetails(badReq)           #6
        return domain.Order{}, statusWithDetails.Err()
    }
    return order, nil
}

The PlaceOrder listing shows a Payment error being resolved, placed in a BadRequest field violation, and attached to an InvalidArgument order status. section 5.3.3

When downstream errors already carry details, status.Convert provides a status whose Details can be inspected. The Order service example extracts BadRequest field violations before grouping their descriptions under the payment field. This preserves useful failure information across service boundaries instead of relying only on a single message. section 5.3.4

func (a Application) PlaceOrder(order domain.Order) (domain.Order, error) {
    err := a.db.Save(&order)
    if err != nil {
        return domain.Order{}, err
    }
    paymentErr := a.payment.Charge(&order)
    if paymentErr != nil {
        st := status.Convert(paymentErr)                               #1
        var allErrors []string                                         #2
        for _, detail := range st.Details() {
            switch t := detail.(type) {
            case *errdetails.BadRequest:                               #3
                for _, violation := range t.GetFieldViolations() {
                    allErrors = append(allErrors, violation.Description)
                }
            }
        }
        fieldErr := &errdetails.BadRequest_FieldViolation{
            Field:       "payment",
            Description: strings.Join(allErrors, "\n"),
        }                                                              #4
        badReq := &errdetails.BadRequest{}
        badReq.FieldViolations = append(badReq.FieldViolations, fieldErr)
        orderStatus := status.New(codes.InvalidArgument, "order creation 
         failed")                                                    #5
        statusWithDetails, _ := orderStatus.WithDetails(badReq)        #6
        return domain.Order{}, statusWithDetails.Err()
    }
    return order, nil
}

The client-side listing shows status.Convert and a type switch over BadRequest details to collect field-violation descriptions. section 5.3.4

How gRPC Microservices in Go covers it

How deep it goes
Works through constructing a status with details and converting downstream errors to inspect field violations.
Examples
Uses a failed Payment charge during Order creation and a grpcurl response showing InvalidArgument with a payment field violation.
What it assumes
Assumes Go gRPC services and client calls, including a service that calls another service through a stub.
What you can do after
Apply it via the Go gRPC status package to return detailed service errors and interpret them in callers.
How it connects
Connects gRPC errors to BadRequest field violations, retries, and circuit breakers.

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.