{"record":{"id":"467a07501b2abc72","repo":"GoogleCloudPlatform/microservices-demo","slug":"could-not-retrieve-products","errorCode":null,"errorMessage":"could not retrieve products","messagePattern":"could not retrieve products","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"src/frontend/handlers.go","lineNumber":69,"sourceCode":"\t\t\t\"renderMoney\":        renderMoney,\n\t\t\t\"renderCurrencyLogo\": renderCurrencyLogo,\n\t\t}).ParseGlob(\"templates/*.html\"))\n\tplat platformDetails\n)\n\nvar validEnvs = []string{\"local\", \"gcp\", \"azure\", \"aws\", \"onprem\", \"alibaba\"}\n\nfunc (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {\n\tlog := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)\n\tlog.WithField(\"currency\", currentCurrency(r)).Info(\"home\")\n\tcurrencies, err := fe.getCurrencies(r.Context())\n\tif err != nil {\n\t\trenderHTTPError(log, r, w, errors.Wrap(err, \"could not retrieve currencies\"), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tproducts, err := fe.getProducts(r.Context())\n\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","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/frontend/handlers.go#L51-L87","documentation":"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.","triggerScenarios":"fe.getProducts(r.Context()) returns error: product catalog service unavailable, RPC error/deadline, or ListProducts returning a failure status.","commonSituations":"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.","solutions":["Check product catalog service pods and logs for startup/loading errors","Verify PRODUCT_CATALOG_SERVICE_ADDR points to the correct service and port","Inspect the wrapped underlying error for the gRPC status code","Confirm the catalog data file is mounted/present in the catalog service","Retry or raise timeouts if the catalog service is intermittently slow"],"exampleFix":"// before\nproducts, err := fe.getProducts(r.Context())\nif err != nil {\n    renderHTTPError(log, r, w, errors.Wrap(err, \"could not retrieve products\"), http.StatusInternalServerError)\n    return\n}\n// after\nproducts, err := fe.getProducts(r.Context())\nif err != nil {\n    log.WithError(err).Error(\"could not retrieve products\")\n    renderHTTPError(log, r, w, errors.Wrap(err, \"could not retrieve products\"), http.StatusServiceUnavailable)\n    return\n}","handlingStrategy":"retry","validationCode":"if fe.productCatalogConn == nil {\n    return nil, errors.New(\"product catalog connection not initialized\")\n}","typeGuard":null,"tryCatchPattern":"products, err := fe.getProducts(r.Context())\nif err != nil {\n    if status.Code(err) == codes.Unavailable {\n        // retry once with backoff before failing the request\n    }\n    renderHTTPError(log, r, w, errors.Wrap(err, \"could not retrieve products\"), http.StatusServiceUnavailable)\n    return\n}","preventionTips":["Ensure catalog service has persistent catalog data mounted","Add gRPC retry policy for idempotent ListProducts calls","Monitor catalog service latency/errors with tracing","Verify PRODUCT_CATALOG_SERVICE_ADDR in every environment"],"tags":["grpc","http","frontend","microservices","catalog"],"backgroundTag":"grpc-rpc-failed","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}