{"record":{"id":"4aba5d1940a82464","repo":"GoogleCloudPlatform/microservices-demo","slug":"cart-failure-v","errorCode":null,"errorMessage":"cart failure: %+v","messagePattern":"cart failure: %\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/checkoutservice/main.go","lineNumber":292,"sourceCode":"\t\tlog.Warnf(\"failed to send order confirmation to %q: %+v\", req.Email, err)\n\t} else {\n\t\tlog.Infof(\"order confirmation email sent to %q\", req.Email)\n\t}\n\tresp := &pb.PlaceOrderResponse{Order: orderResult}\n\treturn resp, nil\n}\n\ntype 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","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/checkoutservice/main.go#L274-L310","documentation":"When checkout's PlaceOrder fails to fetch the user's cart, prepareOrderItemsAndShippingQuoteFromCart wraps the underlying error as 'cart failure: %+v'. This is a contextual wrapper: the real cause (cart service unreachable, FAILED_PRECONDITION from Spanner, empty user id, etc.) is in the wrapped error text.","triggerScenarios":"PlaceOrder calls getUserCart and the cartservice gRPC call returns an error — service down, DNS/network failure, Spanner-backed FAILED_PRECONDITION, or deadline exceeded.","commonSituations":"cartservice pod crashed or not deployed; Spanner misconfiguration in cartservice surfacing as cart failure in checkout; network policies blocking cartservice:7070; user id empty due to missing cart session cookie.","solutions":["Read the wrapped '%+v' detail for the root cause (often a gRPC status)","Check cartservice health/deployment and its connectivity from checkoutservice","Verify the user id/cart session exists for the requesting user","Add retry/backoff for transient cart service unavailability in PlaceOrder"],"exampleFix":"// before\ncartItems, err := cs.getUserCart(ctx, userID)\nif err != nil { return out, fmt.Errorf(\"cart failure: %+v\", err) }\n// after\ncartItems, err := cs.getUserCart(ctx, userID)\nif err != nil {\n    if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {\n        cartItems, err = retryWithBackoff(3, func() error { _, err = cs.getUserCart(ctx, userID); return err })\n        if err != nil { return out, fmt.Errorf(\"cart failure after retries: %+v\", err) }\n    } else {\n        return out, fmt.Errorf(\"cart failure: %+v\", err)\n    }\n}","handlingStrategy":"try-catch","validationCode":"// before PlaceOrder: verify cart service health and non-empty user id\nif userID == \"\" { return errors.New(\"user id required\") }\nresp, err := cartClient.Ping(ctx, &pb.Empty{}) // or gRPC health check\nif err != nil { return fmt.Errorf(\"cartservice unreachable: %w\", err) }","typeGuard":null,"tryCatchPattern":"prep, err := cs.prepareOrderItemsAndShippingQuoteFromCart(ctx, userID, currency, address)\nif err != nil {\n\tif st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {\n\t\treturn retryPlaceOrder(ctx, req) // transient cart service outage\n\t}\n\treturn fmt.Errorf(\"order failed: %w\", err)\n}","preventionTips":["Deploy gRPC health checks and readiness probes for cartservice","Verify cartservice address/DNS in checkoutservice configuration","Retry transient Unavailable errors with backoff before failing the order","Track 'cart failure' occurrences and correlate with cartservice incidents","Monitor cartservice availability and retain wrapped error details (%+v) in structured logs"],"tags":["go","grpc","checkout","error-wrapping"],"backgroundTag":"cart-service-failure","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}