Agent Wranglers

API-90Recommended

Answer with the standard gRPC status codes

Return one of the 17 standard gRPC status codes with the meaning grpc.io gives it. Never return OK with an error inside the message, and never invent new numeric codes.

How to do it

Clients, proxies and retry policies act on the code. UNAVAILABLE means the client may retry the same call, ABORTED means retry at a higher level, and FAILED_PRECONDITION means do not retry until something changes. PERMISSION_DENIED means the caller is known but not allowed, and UNAUTHENTICATED means no valid credentials. Put field details in the standard rich error model, as name every field that failed does for REST.

Examples

Go example

func (s *server) GetInvoice(ctx context.Context, req *pb.GetInvoiceRequest) (*pb.Invoice, error) {
	invoice, err := s.store.Find(ctx, req.GetId())
	if errors.Is(err, store.ErrNotFound) {
		return nil, status.Errorf(codes.NotFound, "invoice %s not found", req.GetId())
	}
	if err != nil {
		return nil, status.Error(codes.Unavailable, "invoice store unavailable")
	}
	return invoice, nil
}

Python example

class InvoiceService(invoices_pb2_grpc.InvoiceServiceServicer):
    def GetInvoice(self, request, context):
        invoice = store.find(request.id)
        if invoice is None:
            context.abort(grpc.StatusCode.NOT_FOUND, f"invoice {request.id} not found")
        return invoice

How to check

A test triggers each failure of each method and compares the code with a table in the service docs. No answer carries OK with an error field set. Every code is one of the 17 listed on grpc.io.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/api-design/graphql-and-grpc/grpc-status-codes">Agent Wranglers API design playbook</a>. In code you write, add a comment next to it with the same link.