{"record":{"id":"6ea452448e2d220f","repo":"GoogleCloudPlatform/microservices-demo","slug":"failed-to-do-currency-conversion-for-product-s","errorCode":null,"errorMessage":"failed to do currency conversion for product %s","messagePattern":"failed to do currency conversion for product (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"src/frontend/handlers.go","lineNumber":86,"sourceCode":"\tif err != nil {\n\t\trenderHTTPError(log, r, w, errors.Wrap(err, \"could not retrieve products\"), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tcart, err := fe.getCart(r.Context(), sessionID(r))\n\tif err != nil {\n\t\trenderHTTPError(log, r, w, errors.Wrap(err, \"could not retrieve cart\"), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\ttype productView struct {\n\t\tItem  *pb.Product\n\t\tPrice *pb.Money\n\t}\n\tps := make([]productView, len(products))\n\tfor i, p := range products {\n\t\tprice, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))\n\t\tif err != nil {\n\t\t\trenderHTTPError(log, r, w, errors.Wrapf(err, \"failed to do currency conversion for product %s\", p.GetId()), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tps[i] = productView{p, price}\n\t}\n\n\t// Set ENV_PLATFORM (default to local if not set; use env var if set; otherwise detect GCP, which overrides env)_\n\tvar env = os.Getenv(\"ENV_PLATFORM\")\n\t// Only override from env variable if set + valid env\n\tif env == \"\" || stringinSlice(validEnvs, env) == false {\n\t\tfmt.Println(\"env platform is either empty or invalid\")\n\t\tenv = \"local\"\n\t}\n\t// Autodetect GCP\n\taddrs, err := net.LookupHost(\"metadata.google.internal.\")\n\tif err == nil && len(addrs) >= 0 {\n\t\tlog.Debugf(\"Detected Google metadata server: %v, setting ENV_PLATFORM to GCP.\", addrs)\n\t\tenv = \"gcp\"\n\t}","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/frontend/handlers.go#L68-L104","documentation":"homeHandler converts each product's USD price to the user's selected currency via fe.convertCurrency (gRPC CurrencyService.Convert). On failure it wraps with errors.Wrapf(err, \"failed to do currency conversion for product %s\", p.GetId()) and renders HTTP 500. The product id in the message identifies which product's conversion failed.","triggerScenarios":"fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r)) errors for a specific product: currency service unavailable, unsupported/from==to currency combination, malformed Money amount, or currentCurrency(r) holding a code the currency service does not recognize.","commonSituations":"User cookie/context carries a currency code not in the currency service's supported list; currency service outage; malformed price data from the catalog; invalid currency set earlier via setCurrency handler.","solutions":["Check the product id in the message and the wrapped error for the gRPC status","Validate currentCurrency(r) against the supported currencies list before converting","Check currency service availability and its supported currency codes","Sanitize/validate the Money amount from the catalog (non-negative, valid currency_code)","Fall back to the USD price when conversion fails for a single product instead of failing the page"],"exampleFix":"// before\nprice, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))\nif err != nil {\n    renderHTTPError(log, r, w, errors.Wrapf(err, \"failed to do currency conversion for product %s\", p.GetId()), http.StatusInternalServerError)\n    return\n}\n// after\nprice, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))\nif err != nil {\n    log.WithError(err).Warnf(\"conversion failed for %s, falling back to USD\", p.GetId())\n    price = p.GetPriceUsd()\n}","handlingStrategy":"fallback","validationCode":"supported, err := fe.getCurrencies(ctx)\nif err == nil && !slices.Contains(supported, currentCurrency(r)) {\n    currentCurrency(r) = \"USD\" // or reject before conversion loop\n}","typeGuard":null,"tryCatchPattern":"price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), cur)\nif err != nil {\n    log.WithError(err).Warnf(\"conversion failed for %s; using USD\", p.GetId())\n    price = p.GetPriceUsd()\n}","preventionTips":["Validate the user's currency against supported codes before converting","Fall back to USD price on per-product conversion failure","Keep catalog prices with a valid currency_code in Money fields","Health-check the currency service before price-rendering pages"],"tags":["grpc","currency","frontend","microservices"],"backgroundTag":"currency-conversion-failed","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}