GoogleCloudPlatform/microservices-demo · error

shipping quote failure: %+v

Error message

shipping quote failure: %+v

What it means

quoteShipping calls ShippingService.GetQuote over gRPC; any failure is wrapped as 'shipping quote failure' by prepareOrderItemsAndShippingQuoteFromCart. It means the checkout flow could not obtain a cost estimate for shipping the cart to the given address. The root cause lives in the shippingservice or the network path to it.

Solutions

  1. Inspect the wrapped gRPC error code in logs to distinguish unavailable vs invalid-argument vs deadline-exceeded.
  2. Check shippingservice health: kubectl get pods, logs, and restart it if crash-looping.
  3. Validate the shipping Address proto has non-empty fields before calling PlaceOrder.
  4. Increase or configure the gRPC/context timeout if deadline-exceeded occurs under load; verify service DNS/connections.

Example fix

// before
shippingUSD, err := cs.quoteShipping(ctx, address, cartItems)
if err != nil {
	return out, fmt.Errorf("shipping quote failure: %+v", err)
}
// after
shippingUSD, err := cs.quoteShipping(ctx, address, cartItems)
if err != nil {
	if status.Code(err) == codes.Unavailable {
		return out, status.Error(codes.Unavailable, "shipping service temporarily unavailable, retry checkout")
	}
	return out, fmt.Errorf("shipping quote failure: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

if address == nil || address.GetStreetAddress() == "" {
	return status.Error(codes.InvalidArgument, "shipping address is required")
}
if len(cartItems) == 0 {
	return status.Error(codes.FailedPrecondition, "cart is empty")
}

Type guard

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

Try / catch

err := placeOrder(ctx, req)
if err != nil {
	if status.Code(err) == codes.Unavailable {
		// exponential backoff retry, e.g. 3 attempts
	}
	if status.Code(err) == codes.DeadlineExceeded {
		// increase timeout or shed load
	}
	return err
}

Prevention

When it happens

Trigger: pb.NewShippingServiceClient(cs.shippingSvcConn).GetQuote returns a gRPC error: shippingservice unavailable, deadline exceeded, invalid/empty address, or malformed cart items.

Common situations: shippingservice pod crashed or OOM-killed; connection pool to shippingservice broken after restart; empty Address proto passed by frontend; context deadline exceeded under load.

Related errors


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

Appendix: source

Thrown at src/checkoutservice/main.go:300

type orderPrep struct {
	orderItems            []*pb.OrderItem
	cartItems             []*pb.CartItem
	shippingCostLocalized *pb.Money
}

func (cs *checkoutService) prepareOrderItemsAndShippingQuoteFromCart(ctx context.Context, userID, userCurrency string, address *pb.Address) (orderPrep, error) {
	var out orderPrep
	cartItems, err := cs.getUserCart(ctx, userID)
	if err != nil {
		return out, fmt.Errorf("cart failure: %+v", err)
	}
	orderItems, err := cs.prepOrderItems(ctx, cartItems, userCurrency)
	if err != nil {
		return out, fmt.Errorf("failed to prepare order: %+v", err)
	}
	shippingUSD, err := cs.quoteShipping(ctx, address, cartItems)
	if err != nil {
		return out, fmt.Errorf("shipping quote failure: %+v", err)
	}
	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 {

View on GitHub (pinned to 72ba613a05)