{"record":{"id":"5a282eb1dc3eec8d","repo":"GoogleCloudPlatform/microservices-demo","slug":"shipping-quote-failure-v","errorCode":null,"errorMessage":"shipping quote failure: %+v","messagePattern":"shipping quote failure: %\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/checkoutservice/main.go","lineNumber":300,"sourceCode":"type orderPrep struct {\n\torderItems            []*pb.OrderItem\n\tcartItems             []*pb.CartItem\n\tshippingCostLocalized *pb.Money\n}\n\nfunc (cs *checkoutService) prepareOrderItemsAndShippingQuoteFromCart(ctx context.Context, userID, userCurrency string, address *pb.Address) (orderPrep, error) {\n\tvar out orderPrep\n\tcartItems, err := cs.getUserCart(ctx, userID)\n\tif err != nil {\n\t\treturn out, fmt.Errorf(\"cart failure: %+v\", err)\n\t}\n\torderItems, err := cs.prepOrderItems(ctx, cartItems, userCurrency)\n\tif err != nil {\n\t\treturn out, fmt.Errorf(\"failed to prepare order: %+v\", err)\n\t}\n\tshippingUSD, err := cs.quoteShipping(ctx, address, cartItems)\n\tif err != nil {\n\t\treturn out, fmt.Errorf(\"shipping quote failure: %+v\", err)\n\t}\n\tshippingPrice, err := cs.convertCurrency(ctx, shippingUSD, userCurrency)\n\tif err != nil {\n\t\treturn out, fmt.Errorf(\"failed to convert shipping cost to currency: %+v\", err)\n\t}\n\n\tout.shippingCostLocalized = shippingPrice\n\tout.cartItems = cartItems\n\tout.orderItems = orderItems\n\treturn out, nil\n}\n\nfunc (cs *checkoutService) quoteShipping(ctx context.Context, address *pb.Address, items []*pb.CartItem) (*pb.Money, error) {\n\tshippingQuote, err := pb.NewShippingServiceClient(cs.shippingSvcConn).\n\t\tGetQuote(ctx, &pb.GetQuoteRequest{\n\t\t\tAddress: address,\n\t\t\tItems:   items})\n\tif err != nil {","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/checkoutservice/main.go#L282-L318","documentation":"quoteShipping calls ShippingService.GetQuote over gRPC; any failure is wrapped as 'shipping quote failure' by prepareOrderItemsAndShippingQuoteFromCart. It means the checkout flow could not obtain a cost estimate for shipping the cart to the given address. The root cause lives in the shippingservice or the network path to it.","triggerScenarios":"pb.NewShippingServiceClient(cs.shippingSvcConn).GetQuote returns a gRPC error: shippingservice unavailable, deadline exceeded, invalid/empty address, or malformed cart items.","commonSituations":"shippingservice pod crashed or OOM-killed; connection pool to shippingservice broken after restart; empty Address proto passed by frontend; context deadline exceeded under load.","solutions":["Inspect the wrapped gRPC error code in logs to distinguish unavailable vs invalid-argument vs deadline-exceeded.","Check shippingservice health: kubectl get pods, logs, and restart it if crash-looping.","Validate the shipping Address proto has non-empty fields before calling PlaceOrder.","Increase or configure the gRPC/context timeout if deadline-exceeded occurs under load; verify service DNS/connections."],"exampleFix":"// before\nshippingUSD, err := cs.quoteShipping(ctx, address, cartItems)\nif err != nil {\n\treturn out, fmt.Errorf(\"shipping quote failure: %+v\", err)\n}\n// after\nshippingUSD, err := cs.quoteShipping(ctx, address, cartItems)\nif err != nil {\n\tif status.Code(err) == codes.Unavailable {\n\t\treturn out, status.Error(codes.Unavailable, \"shipping service temporarily unavailable, retry checkout\")\n\t}\n\treturn out, fmt.Errorf(\"shipping quote failure: %w\", err)\n}","handlingStrategy":"retry","validationCode":"if address == nil || address.GetStreetAddress() == \"\" {\n\treturn status.Error(codes.InvalidArgument, \"shipping address is required\")\n}\nif len(cartItems) == 0 {\n\treturn status.Error(codes.FailedPrecondition, \"cart is empty\")\n}","typeGuard":"func hasValidAddress(a *pb.Address) bool {\n\treturn a != nil && a.GetStreetAddress() != \"\" && a.GetCity() != \"\" && a.GetCountry() != \"\"\n}","tryCatchPattern":"err := placeOrder(ctx, req)\nif err != nil {\n\tif status.Code(err) == codes.Unavailable {\n\t\t// exponential backoff retry, e.g. 3 attempts\n\t}\n\tif status.Code(err) == codes.DeadlineExceeded {\n\t\t// increase timeout or shed load\n\t}\n\treturn err\n}","preventionTips":["Add gRPC retry policy for Unavailable on the shipping connection","Validate address fields client-side before checkout","Set sane per-RPC deadlines instead of none","Monitor shippingservice health with readiness probes"],"tags":["grpc","shipping","microservices","timeout"],"backgroundTag":"downstream-grpc-call-failed","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}