GoogleCloudPlatform/microservices-demo · error

failed to convert shipping cost to currency: %+v

Error message

failed to convert shipping cost to currency: %+v

What it means

convertCurrency calls CurrencyService.Convert; if the conversion of the shipping cost (originally USD) to the user's currency fails, this wrapper is emitted. It means the currency service rejected or could not process the conversion request. Only the shipping-cost conversion path raises this exact message (product-price conversion uses a different wrapper).

Source

Thrown at src/checkoutservice/main.go:304

}

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 {
		return nil, fmt.Errorf("failed to get shipping quote: %+v", err)
	}
	return shippingQuote.GetCostUsd(), nil
}

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Log the wrapped error and check its gRPC status code (Unavailable vs InvalidArgument).
  2. Validate userCurrency is in currencyservice's supported currencies before checkout.
  3. Check currencyservice pods/logs and restart if unhealthy.
  4. Verify cs.currencySvcConn is dialed to the correct service address at startup.
  5. Replace context.TODO() with the request ctx so cancellation/timeouts propagate.

Example fix

// before
result, err := pb.NewCurrencyServiceClient(cs.currencySvcConn).Convert(context.TODO(), &pb.CurrencyConversionRequest{
	From:   from,
	ToCode: toCurrency})
// after
result, err := pb.NewCurrencyServiceClient(cs.currencySvcConn).Convert(ctx, &pb.CurrencyConversionRequest{
	From:   from,
	ToCode: toCurrency})
Defensive patterns

Strategy: validation

Validate before calling

supported, err := currencyClient.GetSupportedCurrencies(ctx, &emptypb.Empty{})
if err != nil {
	return err
}
if !slices.Contains(supported.GetCurrencyCodes(), userCurrency) {
	return status.Error(codes.InvalidArgument, "unsupported currency: "+userCurrency)
}

Type guard

func isConvertible(m *pb.Money, code string) bool {
	return m != nil && m.GetCurrencyCode() != "" && code != ""
}

Try / catch

shippingPrice, err := cs.convertCurrency(ctx, shippingUSD, userCurrency)
if err != nil {
	if status.Code(err) == codes.InvalidArgument {
		return status.Errorf(codes.InvalidArgument, "cannot convert to %s", userCurrency)
	}
	return fmt.Errorf("failed to convert shipping cost to currency: %w", err)
}

Prevention

When it happens

Trigger: CurrencyService.Convert returns an error for {from: shippingUSD, toCode: userCurrency}: unsupported target currency, empty Money struct, currencyservice unreachable, or the internal context.TODO() call timing out.

Common situations: User supplied a currency code not in the currency service's supported list; currencyservice deployment down; env var CURRENCY_SERVICE not wired so the connection points nowhere; load-induced gRPC deadline exceeded.

Related errors


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