GoogleCloudPlatform/microservices-demo · error

failed to get shipping quote: %+v

Error message

failed to get shipping quote: %+v

What it means

quoteShipping is the inner wrapper: the gRPC GetQuote call to shippingservice returned an error and is wrapped with 'failed to get shipping quote'. The shipping service prices a cart for a destination address; failure here blocks checkout. Error 21 is this error re-wrapped by the caller.

Source

Thrown at src/checkoutservice/main.go:319

	}
	shippingPrice, err := cs.convertCurrency(ctx, shippingUSD, userCurrency)
	if err != nil {
		return out, fmt.Errorf("failed to convert shipping cost to currency: %+v", err)
	}

	out.shippingCostLocalized = shippingPrice
	out.cartItems = cartItems
	out.orderItems = orderItems
	return out, nil
}

func (cs *checkoutService) quoteShipping(ctx context.Context, address *pb.Address, items []*pb.CartItem) (*pb.Money, error) {
	shippingQuote, err := pb.NewShippingServiceClient(cs.shippingSvcConn).
		GetQuote(ctx, &pb.GetQuoteRequest{
			Address: address,
			Items:   items})
	if err != nil {
		return nil, fmt.Errorf("failed to get shipping quote: %+v", err)
	}
	return shippingQuote.GetCostUsd(), nil
}

func (cs *checkoutService) getUserCart(ctx context.Context, userID string) ([]*pb.CartItem, error) {
	cart, err := pb.NewCartServiceClient(cs.cartSvcConn).GetCart(ctx, &pb.GetCartRequest{UserId: userID})
	if err != nil {
		return nil, fmt.Errorf("failed to get user cart during checkout: %+v", err)
	}
	return cart.GetItems(), nil
}

func (cs *checkoutService) emptyUserCart(ctx context.Context, userID string) error {
	if _, err := pb.NewCartServiceClient(cs.cartSvcConn).EmptyCart(ctx, &pb.EmptyCartRequest{UserId: userID}); err != nil {
		return fmt.Errorf("failed to empty user cart during checkout: %+v", err)
	}
	return nil
}

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Check the gRPC status code of the wrapped error to identify unavailable vs invalid-argument.
  2. Validate the Address and Items are non-empty/valid before calling GetQuote.
  3. Check shippingservice health and logs; restart crash-looping pods.
  4. Ensure checkoutservice can resolve and reach shippingservice (DNS, network policies, correct port).

Example fix

// before
shippingQuote, err := pb.NewShippingServiceClient(cs.shippingSvcConn).
	GetQuote(ctx, &pb.GetQuoteRequest{Address: address, Items: items})
if err != nil {
	return nil, fmt.Errorf("failed to get shipping quote: %+v", err)
}
// after
if address == nil || items == nil {
	return nil, status.Error(codes.InvalidArgument, "address and items are required for a shipping quote")
}
shippingQuote, err := pb.NewShippingServiceClient(cs.shippingSvcConn).
	GetQuote(ctx, &pb.GetQuoteRequest{Address: address, Items: items})
if err != nil {
	return nil, fmt.Errorf("failed to get shipping quote: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if !hasValidAddress(address) || len(items) == 0 {
	return status.Error(codes.InvalidArgument, "address and items required for quote")
}

Type guard

func hasValidAddress(a *pb.Address) bool {
	return a != nil && a.GetStreetAddress() != "" && a.GetCountry() != ""
}

Try / catch

shippingQuote, err := shippingClient.GetQuote(ctx, req)
if err != nil {
	switch status.Code(err) {
	case codes.Unavailable:
		return retryWithBackoff(ctx, req)
	case codes.InvalidArgument:
		return status.Error(codes.InvalidArgument, "check address and cart items")
	default:
		return fmt.Errorf("failed to get shipping quote: %w", err)
	}
}

Prevention

When it happens

Trigger: pb.NewShippingServiceClient(cs.shippingSvcConn).GetQuote(ctx, &pb.GetQuoteRequest{Address, Items}) returns a non-nil error: unavailable service, invalid argument (nil/empty address or items), or deadline exceeded.

Common situations: Frontend sent an Address with empty fields; shippingservice restarted and the connection went stale; cross-service network policy blocked the port; sustained load causing context cancellation.

Related errors


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