GoogleCloudPlatform/microservices-demo · error · ErrMismatchingCurrency
mismatching currency codes
Error message
mismatching currency codes
What it means
ErrMismatchingCurrency is returned by money.Sum when the two operands have different CurrencyCode values. Adding money across currencies is meaningless, so the library rejects it explicitly instead of adding raw numbers.
Source
Thrown at src/checkoutservice/money/money.go:31
// limitations under the License.
package money
import (
"errors"
pb "github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/genproto"
)
const (
nanosMin = -999999999
nanosMax = +999999999
nanosMod = 1000000000
)
var (
ErrInvalidValue = errors.New("one of the specified money values is invalid")
ErrMismatchingCurrency = errors.New("mismatching currency codes")
)
// IsValid checks if specified value has a valid units/nanos signs and ranges.
func IsValid(m pb.Money) bool {
return signMatches(m) && validNanos(m.GetNanos())
}
func signMatches(m pb.Money) bool {
return m.GetNanos() == 0 || m.GetUnits() == 0 || (m.GetNanos() < 0) == (m.GetUnits() < 0)
}
func validNanos(nanos int32) bool { return nanosMin <= nanos && nanos <= nanosMax }
// IsZero returns true if the specified money value is equal to zero.
func IsZero(m pb.Money) bool { return m.GetUnits() == 0 && m.GetNanos() == 0 }
// IsPositive returns true if the specified money value is valid and is
// positive.View on GitHub (pinned to 72ba613a05)
Solutions
- Convert one operand to the other's currency before summing (use currencyconversion service)
- Compare l.GetCurrencyCode() == r.GetCurrencyCode() before calling Sum
- Ensure the catalog/store returns prices in a consistent currency for the order
- Check where the currency code was set (product price vs user currency) for divergence
Example fix
// before
if l.GetCurrencyCode() != r.GetCurrencyCode() {
return pb.Money{}, ErrMismatchingCurrency
}
// after
if l.GetCurrencyCode() != r.GetCurrencyCode() {
r, err = convert(r, l.GetCurrencyCode()) // convert via currency service first
if err != nil { return pb.Money{}, err }
} Defensive patterns
Strategy: validation
Validate before calling
func safeSum(l, r pb.Money) (pb.Money, error) {
if l.GetCurrencyCode() != r.GetCurrencyCode() {
return pb.Money{}, fmt.Errorf("currency mismatch: %s vs %s", l.GetCurrencyCode(), r.GetCurrencyCode())
}
return money.Sum(l, r)
} Type guard
func sameCurrency(l, r pb.Money) bool {
return l.GetCurrencyCode() == r.GetCurrencyCode()
} Try / catch
sum, err := money.Sum(l, r)
if err != nil {
if errors.Is(err, money.ErrMismatchingCurrency) {
return fmt.Errorf("convert %s to %s before summing", r.GetCurrencyCode(), l.GetCurrencyCode())
}
return err
} Prevention
- Convert all prices to the user's currency before any summation
- Re-convert cart item prices when the user changes currency
- Enforce a single currency code per order at the API boundary
- Check catalog data for inconsistent currency codes
When it happens
Trigger: Calling Sum (directly or via checkout order-item/product price aggregation) with prices denominated in different currency codes, e.g. USD price plus EUR price.
Common situations: Products priced in different currencies in the catalog; user currency conversion skipped or failed; cart items added under one currency then displayed/ordered under another.
Related errors
- mismatching currency codes
- one of the specified money values is invalid
- one of the specified money values is invalid
- product id not specified
- invalid validation error format
AI-assisted analysis of GoogleCloudPlatform/microservices-demo@72ba613a05 (2026-09-02).
Data as JSON: /api/errors/ee09476bb96ded05.
Report an issue: GitHub.