GoogleCloudPlatform/microservices-demo · error

failed to do currency conversion for product %s

Error message

failed to do currency conversion for product %s

What it means

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.

Source

Thrown at src/frontend/handlers.go:86

	if err != nil {
		renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve products"), http.StatusInternalServerError)
		return
	}
	cart, err := fe.getCart(r.Context(), sessionID(r))
	if err != nil {
		renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
		return
	}

	type productView struct {
		Item  *pb.Product
		Price *pb.Money
	}
	ps := make([]productView, len(products))
	for i, p := range products {
		price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
		if err != nil {
			renderHTTPError(log, r, w, errors.Wrapf(err, "failed to do currency conversion for product %s", p.GetId()), http.StatusInternalServerError)
			return
		}
		ps[i] = productView{p, price}
	}

	// Set ENV_PLATFORM (default to local if not set; use env var if set; otherwise detect GCP, which overrides env)_
	var env = os.Getenv("ENV_PLATFORM")
	// Only override from env variable if set + valid env
	if env == "" || stringinSlice(validEnvs, env) == false {
		fmt.Println("env platform is either empty or invalid")
		env = "local"
	}
	// Autodetect GCP
	addrs, err := net.LookupHost("metadata.google.internal.")
	if err == nil && len(addrs) >= 0 {
		log.Debugf("Detected Google metadata server: %v, setting ENV_PLATFORM to GCP.", addrs)
		env = "gcp"
	}

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Check the product id in the message and the wrapped error for the gRPC status
  2. Validate currentCurrency(r) against the supported currencies list before converting
  3. Check currency service availability and its supported currency codes
  4. Sanitize/validate the Money amount from the catalog (non-negative, valid currency_code)
  5. Fall back to the USD price when conversion fails for a single product instead of failing the page

Example fix

// before
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
if err != nil {
    renderHTTPError(log, r, w, errors.Wrapf(err, "failed to do currency conversion for product %s", p.GetId()), http.StatusInternalServerError)
    return
}
// after
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
if err != nil {
    log.WithError(err).Warnf("conversion failed for %s, falling back to USD", p.GetId())
    price = p.GetPriceUsd()
}
Defensive patterns

Strategy: fallback

Validate before calling

supported, err := fe.getCurrencies(ctx)
if err == nil && !slices.Contains(supported, currentCurrency(r)) {
    currentCurrency(r) = "USD" // or reject before conversion loop
}

Try / catch

price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), cur)
if err != nil {
    log.WithError(err).Warnf("conversion failed for %s; using USD", p.GetId())
    price = p.GetPriceUsd()
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of GoogleCloudPlatform/microservices-demo@72ba613a05 (2026-09-02). Data as JSON: /api/errors/6ea452448e2d220f. Report an issue: GitHub.