GoogleCloudPlatform/microservices-demo · error

could not retrieve products

Error message

could not retrieve products

What it means

homeHandler fetches the product catalog via fe.getProducts (gRPC ProductCatalogService.ListProducts). On error it wraps with errors.Wrap(err, "could not retrieve products") and renders HTTP 500, since the home page cannot display products.

Source

Thrown at src/frontend/handlers.go:69

			"renderMoney":        renderMoney,
			"renderCurrencyLogo": renderCurrencyLogo,
		}).ParseGlob("templates/*.html"))
	plat platformDetails
)

var validEnvs = []string{"local", "gcp", "azure", "aws", "onprem", "alibaba"}

func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
	log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
	log.WithField("currency", currentCurrency(r)).Info("home")
	currencies, err := fe.getCurrencies(r.Context())
	if err != nil {
		renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
		return
	}
	products, err := fe.getProducts(r.Context())
	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

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Check product catalog service pods and logs for startup/loading errors
  2. Verify PRODUCT_CATALOG_SERVICE_ADDR points to the correct service and port
  3. Inspect the wrapped underlying error for the gRPC status code
  4. Confirm the catalog data file is mounted/present in the catalog service
  5. Retry or raise timeouts if the catalog service is intermittently slow

Example fix

// before
products, err := fe.getProducts(r.Context())
if err != nil {
    renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve products"), http.StatusInternalServerError)
    return
}
// after
products, err := fe.getProducts(r.Context())
if err != nil {
    log.WithError(err).Error("could not retrieve products")
    renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve products"), http.StatusServiceUnavailable)
    return
}
Defensive patterns

Strategy: retry

Validate before calling

if fe.productCatalogConn == nil {
    return nil, errors.New("product catalog connection not initialized")
}

Try / catch

products, err := fe.getProducts(r.Context())
if err != nil {
    if status.Code(err) == codes.Unavailable {
        // retry once with backoff before failing the request
    }
    renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve products"), http.StatusServiceUnavailable)
    return
}

Prevention

When it happens

Trigger: fe.getProducts(r.Context()) returns error: product catalog service unavailable, RPC error/deadline, or ListProducts returning a failure status.

Common situations: Product catalog service crash-looping or not deployed; PRODUCT_CATALOG_SERVICE_ADDR misconfigured; catalog data failing to load in the service (empty products.csv mount); deadlines hit when the catalog service is overloaded.

Related errors


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