GoogleCloudPlatform/microservices-demo · error

shipment failed: %+v

Error message

shipment failed: %+v

What it means

checkoutservice's shipOrder wraps any error returned by the ShippingService gRPC ShipOrder call with fmt.Errorf("shipment failed: %+v", err). It means the downstream shipping service rejected the request or the RPC failed (transport error, deadline, or application-level error). The %+v verb renders the full error chain including wrapped gRPC status details.

Source

Thrown at src/checkoutservice/main.go:391

	if err != nil {
		return "", fmt.Errorf("could not charge the card: %+v", err)
	}
	return paymentResp.GetTransactionId(), nil
}

func (cs *checkoutService) sendOrderConfirmation(ctx context.Context, email string, order *pb.OrderResult) error {
	_, err := pb.NewEmailServiceClient(cs.emailSvcConn).SendOrderConfirmation(ctx, &pb.SendOrderConfirmationRequest{
		Email: email,
		Order: order})
	return err
}

func (cs *checkoutService) shipOrder(ctx context.Context, address *pb.Address, items []*pb.CartItem) (string, error) {
	resp, err := pb.NewShippingServiceClient(cs.shippingSvcConn).ShipOrder(ctx, &pb.ShipOrderRequest{
		Address: address,
		Items:   items})
	if err != nil {
		return "", fmt.Errorf("shipment failed: %+v", err)
	}
	return resp.GetTrackingId(), nil
}

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Check the shipping service is running and reachable: kubectl get pods / test the service endpoint on its gRPC port
  2. Read the wrapped %+v error for the gRPC status code to identify transport vs application failure
  3. Verify the shipping service address env var (e.g. SHIPPING_SERVICE_ADDR) points at the correct host:port
  4. Add or increase the client timeout on the ShipOrder context if DeadlineExceeded
  5. Validate address/items payload before calling ShipOrder to avoid application-level rejections

Example fix

// before
return "", fmt.Errorf("shipment failed: %+v", err)
// after
if status.Code(err) == codes.Unavailable {
    return "", fmt.Errorf("shipment failed (shipping service unavailable, retry): %w", err)
}
return "", fmt.Errorf("shipment failed: %w", err)
Defensive patterns

Strategy: retry

Validate before calling

if address == nil || len(items) == 0 {
    return "", errors.New("shipOrder: address and items are required")
}
if cs.shippingSvcConn == nil {
    return "", errors.New("shipOrder: shipping service connection not initialized")
}

Try / catch

trackingID, err := cs.shipOrder(ctx, addr, items)
if err != nil {
    if status.Code(err) == codes.Unavailable || status.Code(err) == codes.DeadlineExceeded {
        // retry with backoff
    }
    return fmt.Errorf("order placement aborted: %w", err)
}

Prevention

When it happens

Trigger: pb.NewShippingServiceClient(cs.shippingSvcConn).ShipOrder(ctx, &pb.ShipOrderRequest{...}) returns a non-nil err: connection failure to the shipping service, gRPC Unavailable/DeadlineExceeded, or the shipping service rejecting the address/items payload.

Common situations: Shipping service pod down or not deployed; wrong SHIPPING_SERVICE_ADDR; network policy blocking the port; quote/shipping request timing out under load; invalid address causing the shipping service to return an error status.

Related errors


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