GoogleCloudPlatform/microservices-demo · error

could not retrieve currencies

Error message

could not retrieve currencies

What it means

homeHandler fetches supported currencies via fe.getCurrencies (gRPC to the currency service). On any error it wraps with errors.Wrap(err, "could not retrieve currencies") and renders HTTP 500. This indicates the frontend could not obtain the currency list, so the home page cannot render prices.

Source

Thrown at src/frontend/handlers.go:64

	frontendMessage  = strings.TrimSpace(os.Getenv("FRONTEND_MESSAGE"))
	isCymbalBrand    = "true" == strings.ToLower(os.Getenv("CYMBAL_BRANDING"))
	assistantEnabled = "true" == strings.ToLower(os.Getenv("ENABLE_ASSISTANT"))
	templates        = template.Must(template.New("").
				Funcs(template.FuncMap{
			"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))

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Check currency service health/deployment (kubectl get pods, logs)
  2. Verify CURRENCY_SERVICE_ADDR resolves to the currency service host:port
  3. Inspect the wrapped cause (%+v / errors.Unwrap) for the gRPC status code
  4. Increase context timeout if DeadlineExceeded under load
  5. Add a fallback default currency list so the home page renders when currency service is down

Example fix

// before
currencies, err := fe.getCurrencies(r.Context())
if err != nil {
    renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
    return
}
// after
currencies, err := fe.getCurrencies(r.Context())
if err != nil {
    log.WithError(err).Warn("could not retrieve currencies, using fallback")
    currencies = defaultCurrencies
}
Defensive patterns

Strategy: fallback

Validate before calling

if cs.currencySvcConn == nil {
    return nil, errors.New("currency service connection not initialized")
}

Try / catch

currencies, err := fe.getCurrencies(r.Context())
if err != nil {
    log.WithError(err).Warn("currency list unavailable, using fallback")
    currencies = defaultCurrencies
}

Prevention

When it happens

Trigger: fe.getCurrencies(r.Context()) returns error: currency service unavailable, RPC deadline exceeded, or empty/error response from CurrencyService.GetSupportedCurrencies.

Common situations: Currency service pod down or crash-looping; CURRENCY_SERVICE_ADDR wrong; context deadline exceeded under load; network policy blocking frontend→currency traffic; service not deployed in the cluster.

Related errors


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