{"record":{"id":"40958b6717fdc918","repo":"GoogleCloudPlatform/microservices-demo","slug":"failed-to-get-product-q","errorCode":null,"errorMessage":"failed to get product #%q","messagePattern":"failed to get product #%q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/checkoutservice/main.go","lineNumber":346,"sourceCode":"\t}\n\treturn cart.GetItems(), nil\n}\n\nfunc (cs *checkoutService) emptyUserCart(ctx context.Context, userID string) error {\n\tif _, err := pb.NewCartServiceClient(cs.cartSvcConn).EmptyCart(ctx, &pb.EmptyCartRequest{UserId: userID}); err != nil {\n\t\treturn fmt.Errorf(\"failed to empty user cart during checkout: %+v\", err)\n\t}\n\treturn nil\n}\n\nfunc (cs *checkoutService) prepOrderItems(ctx context.Context, items []*pb.CartItem, userCurrency string) ([]*pb.OrderItem, error) {\n\tout := make([]*pb.OrderItem, len(items))\n\tcl := pb.NewProductCatalogServiceClient(cs.productCatalogSvcConn)\n\n\tfor i, item := range items {\n\t\tproduct, err := cl.GetProduct(ctx, &pb.GetProductRequest{Id: item.GetProductId()})\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to get product #%q\", item.GetProductId())\n\t\t}\n\t\tprice, err := cs.convertCurrency(ctx, product.GetPriceUsd(), userCurrency)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to convert price of %q to %s\", item.GetProductId(), userCurrency)\n\t\t}\n\t\tout[i] = &pb.OrderItem{\n\t\t\tItem: item,\n\t\t\tCost: price}\n\t}\n\treturn out, nil\n}\n\nfunc (cs *checkoutService) convertCurrency(ctx context.Context, from *pb.Money, toCurrency string) (*pb.Money, error) {\n\tresult, err := pb.NewCurrencyServiceClient(cs.currencySvcConn).Convert(context.TODO(), &pb.CurrencyConversionRequest{\n\t\tFrom:   from,\n\t\tToCode: toCurrency})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to convert currency: %+v\", err)","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/checkoutservice/main.go#L328-L364","documentation":"prepOrderItems fails when ProductCatalogService.GetProduct errors for a cart item; the product ID is interpolated with %q. Note the underlying error is swallowed (not wrapped), so only the product ID is visible. Commonly caused by cart entries referencing products that no longer exist in the catalog.","triggerScenarios":"cl.GetProduct(ctx, &pb.GetProductRequest{Id: item.GetProductId()}) returns an error: product ID not found in the catalog, catalog service unavailable, or RPC deadline exceeded.","commonSituations":"Stale cart data referencing removed/renamed product SKUs; productcatalogservice pod down; catalog data re-seeded with different IDs; typo'd product ID injected by clients.","solutions":["Verify the product ID exists via ProductCatalogService.ListProducts or the catalog data (products.json).","Check productcatalogservice health and logs.","Wrap the underlying error (%w) so root cause is visible in logs instead of being discarded.","Clean up stale carts: validate cart items against the catalog before checkout, or evict unknown IDs.","Ensure checkoutservice can reach productcatalogservice over gRPC."],"exampleFix":"// before\nproduct, err := cl.GetProduct(ctx, &pb.GetProductRequest{Id: item.GetProductId()})\nif err != nil {\n\treturn nil, fmt.Errorf(\"failed to get product #%q\", item.GetProductId())\n}\n// after\nproduct, err := cl.GetProduct(ctx, &pb.GetProductRequest{Id: item.GetProductId()})\nif err != nil {\n\treturn nil, fmt.Errorf(\"failed to get product #%q: %w\", item.GetProductId(), err)\n}","handlingStrategy":"validation","validationCode":"// validate cart items against the catalog before checkout\nfor _, item := range cartItems {\n\tif _, err := catalogClient.GetProduct(ctx, &pb.GetProductRequest{Id: item.GetProductId()}); err != nil {\n\t\t// remove item from cart or reject checkout early\n\t}\n}","typeGuard":"func isValidProductID(id string) bool {\n\treturn id != \"\" && productCatalogContains(id) // cached catalog ID set\n}","tryCatchPattern":"product, err := catalogClient.GetProduct(ctx, req)\nif err != nil {\n\tif status.Code(err) == codes.NotFound {\n\t\treturn fmt.Errorf(\"product %q no longer exists: %w\", id, err)\n\t}\n\treturn fmt.Errorf(\"failed to get product %q: %w\", id, err)\n}","preventionTips":["Always wrap with %w — never discard the underlying error","Evict deleted product IDs from carts","Re-seed catalog with stable IDs","Monitor catalog service availability"],"tags":["grpc","product-catalog","microservices","data-integrity"],"backgroundTag":"product-not-found","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}