GoogleCloudPlatform/microservices-demo · error

cart failure: %+v

Error message

cart failure: %+v

What it means

When checkout's PlaceOrder fails to fetch the user's cart, prepareOrderItemsAndShippingQuoteFromCart wraps the underlying error as 'cart failure: %+v'. This is a contextual wrapper: the real cause (cart service unreachable, FAILED_PRECONDITION from Spanner, empty user id, etc.) is in the wrapped error text.

Source

Thrown at src/checkoutservice/main.go:292

		log.Warnf("failed to send order confirmation to %q: %+v", req.Email, err)
	} else {
		log.Infof("order confirmation email sent to %q", req.Email)
	}
	resp := &pb.PlaceOrderResponse{Order: orderResult}
	return resp, nil
}

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

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Read the wrapped '%+v' detail for the root cause (often a gRPC status)
  2. Check cartservice health/deployment and its connectivity from checkoutservice
  3. Verify the user id/cart session exists for the requesting user
  4. Add retry/backoff for transient cart service unavailability in PlaceOrder

Example fix

// before
cartItems, err := cs.getUserCart(ctx, userID)
if err != nil { return out, fmt.Errorf("cart failure: %+v", err) }
// after
cartItems, err := cs.getUserCart(ctx, userID)
if err != nil {
    if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {
        cartItems, err = retryWithBackoff(3, func() error { _, err = cs.getUserCart(ctx, userID); return err })
        if err != nil { return out, fmt.Errorf("cart failure after retries: %+v", err) }
    } else {
        return out, fmt.Errorf("cart failure: %+v", err)
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before PlaceOrder: verify cart service health and non-empty user id
if userID == "" { return errors.New("user id required") }
resp, err := cartClient.Ping(ctx, &pb.Empty{}) // or gRPC health check
if err != nil { return fmt.Errorf("cartservice unreachable: %w", err) }

Try / catch

prep, err := cs.prepareOrderItemsAndShippingQuoteFromCart(ctx, userID, currency, address)
if err != nil {
	if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {
		return retryPlaceOrder(ctx, req) // transient cart service outage
	}
	return fmt.Errorf("order failed: %w", err)
}

Prevention

When it happens

Trigger: PlaceOrder calls getUserCart and the cartservice gRPC call returns an error — service down, DNS/network failure, Spanner-backed FAILED_PRECONDITION, or deadline exceeded.

Common situations: cartservice pod crashed or not deployed; Spanner misconfiguration in cartservice surfacing as cart failure in checkout; network policies blocking cartservice:7070; user id empty due to missing cart session cookie.

Related errors


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