GoogleCloudPlatform/microservices-demo · error · ErrInvalidValue

one of the specified money values is invalid

Error message

one of the specified money values is invalid

What it means

The frontend carries an identical copy of the money helper (src/frontend/money/money.go), whose ErrInvalidValue is declared at money.go:30. It means a pb.Money operand failed IsValid: units/nanos signs mismatch or nanos out of range. Sum refuses arithmetic on malformed money.

Source

Thrown at src/frontend/money/money.go:30

// See the License for the specific language governing permissions and
// limitations under the License.

package money

import (
	"errors"

	pb "github.com/GoogleCloudPlatform/microservices-demo/src/frontend/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

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Validate with IsValid before summing
  2. Normalize nanos into units so the value satisfies signMatches && validNanos
  3. Fix the producer that emits invalid Money values
  4. Consider deduplicating the money package into a shared module to avoid drift

Example fix

// before
out, _ := money.Sum(invalidMoney, other)
// after
if !money.IsValid(invalidMoney) {
    return pb.Money{}, fmt.Errorf("invalid money: %+v", invalidMoney)
}
out, err := money.Sum(invalidMoney, other)
Defensive patterns

Strategy: validation

Validate before calling

if !money.IsValid(price) {
	return errors.New("price failed IsValid: units/nanos sign mismatch or nanos out of range")
}
out, err := money.Sum(price, other)

Type guard

func isValidMoney(m pb.Money) bool { return money.IsValid(m) }

Try / catch

out, err := money.Sum(l, r)
if errors.Is(err, money.ErrInvalidValue) {
	return fmt.Errorf("invalid money operand: %+v / %+v", l, r)
}

Prevention

When it happens

Trigger: Same as error 13: Sum called with units/nanos of opposite signs or |nanos| >= 1000000000, e.g. a Money built from un-normalized external input.

Common situations: Duplicated money package drift between frontend and checkoutservice; price values built by hand or converted from floats; protobuf Money produced by another service without validation.

Related errors


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