GoogleCloudPlatform/microservices-demo · error

could not retrieve product #%s

Error message

could not retrieve product #%s

What it means

While building the cart item views, viewCartHandler failed to fetch one of the products in the cart from productcatalogservice (fe.getProduct). The error uses errors.Wrapf with the product ID and is rendered as HTTP 500, aborting the whole cart page.

Source

Thrown at src/frontend/handlers.go:287

	}

	shippingCost, err := fe.getShippingQuote(r.Context(), cart, currentCurrency(r))
	if err != nil {
		renderHTTPError(log, r, w, errors.Wrap(err, "failed to get shipping quote"), http.StatusInternalServerError)
		return
	}

	type cartItemView struct {
		Item     *pb.Product
		Quantity int32
		Price    *pb.Money
	}
	items := make([]cartItemView, len(cart))
	totalPrice := pb.Money{CurrencyCode: currentCurrency(r)}
	for i, item := range cart {
		p, err := fe.getProduct(r.Context(), item.GetProductId())
		if err != nil {
			renderHTTPError(log, r, w, errors.Wrapf(err, "could not retrieve product #%s", item.GetProductId()), http.StatusInternalServerError)
			return
		}
		price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
		if err != nil {
			renderHTTPError(log, r, w, errors.Wrapf(err, "could not convert currency for product #%s", item.GetProductId()), http.StatusInternalServerError)
			return
		}

		multPrice := money.MultiplySlow(*price, uint32(item.GetQuantity()))
		items[i] = cartItemView{
			Item:     p,
			Quantity: item.GetQuantity(),
			Price:    &multPrice}
		totalPrice = money.Must(money.Sum(totalPrice, multPrice))
	}
	totalPrice = money.Must(money.Sum(totalPrice, *shippingCost))
	year := time.Now().Year()

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Remove the offending product ID from the user's cart or purge stale cart entries.
  2. Check productcatalogservice availability and its data file.
  3. Verify PRODUCT_CATALOG_SERVICE_ADDR configuration.
  4. Skip missing products gracefully (warn + exclude item) instead of failing the entire cart page.

Example fix

// before
p, err := fe.getProduct(r.Context(), item.GetProductId())
if err != nil {
    renderHTTPError(log, r, w, errors.Wrapf(err, "could not retrieve product #%s", item.GetProductId()), http.StatusInternalServerError)
// after
p, err := fe.getProduct(r.Context(), item.GetProductId())
if err != nil {
    log.WithField("product", item.GetProductId()).Warn("product missing from catalog, skipping cart item")
    continue // or remove item from cart via fe.insertCart(..., 0)
Defensive patterns

Strategy: fallback

Validate before calling

// check cart entries reference live catalog IDs before rendering
for _, item := range cart {
    if item.GetProductId() == "" {
        log.Warn("cart item missing product id")
    }
}

Try / catch

p, err := fe.getProduct(r.Context(), item.GetProductId())
if err != nil {
    log.WithField("product", item.GetProductId()).Warn("missing product; skipping cart item")
    continue
}

Prevention

When it happens

Trigger: GET /cart when any product_id stored in the cart no longer resolves via productcatalogservice (item removed from catalog) or the catalog RPC fails.

Common situations: cart contains a stale product ID after a catalog update/redeploy of productcatalogservice data, catalog service outage, PRODUCT_CATALOG_SERVICE_ADDR misconfigured.

Related errors


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