GoogleCloudPlatform/microservices-demo · warning

invalid validation error format

Error message

invalid validation error format

What it means

validator.ValidationErrorResponse converts a validator.ValidationErrors value into a readable message. If the passed err is not actually a validator.ValidationErrors (a failed type assertion), it returns the generic error 'invalid validation error format'. It guards against feeding the wrong error type into the formatting helper.

Source

Thrown at src/frontend/validator/validator.go:76

// Implementations of the 'Payload' interface.
func (ad *AddToCartPayload) Validate() error {
	return validate.Struct(ad)
}

func (po *PlaceOrderPayload) Validate() error {
	return validate.Struct(po)
}

func (sc *SetCurrencyPayload) Validate() error {
	return validate.Struct(sc)
}

// Reusable error response function.
func ValidationErrorResponse(err error) error {
	validationErrs, ok := err.(validator.ValidationErrors)
	if !ok {
		return errors.New("invalid validation error format")
	}
	var msg string
	for _, err := range validationErrs {
		msg += fmt.Sprintf("Field '%s' is invalid: %s\n", err.Field(), err.Tag())
	}
	return fmt.Errorf("%s", msg)
}

View on GitHub (pinned to 72ba613a05)

Solutions

  1. Pass the raw error returned by validator.Struct(...) directly, without wrapping
  2. Check the type before calling: only invoke ValidationErrorResponse when errors.As(err, &validator.ValidationErrors{})
  3. Fix call sites (addToCartHandler, placeOrderHandler, setCurrencyHandler) that wrap the validator error
  4. Log the original error to see what type actually arrived

Example fix

// before
if err := validator.New().Struct(req); err != nil {
    return ValidationErrorResponse(fmt.Errorf("cart error: %w", err))
}
// after
if err := validator.New().Struct(req); err != nil {
    return ValidationErrorResponse(err) // pass unwrapped ValidationErrors
}
Defensive patterns

Strategy: type-guard

Validate before calling

var vErr validator.ValidationErrors
if errors.As(err, &vErr) {
	return ValidationErrorResponse(err) // safe: concrete type present
}
return err // pass through non-validator errors untouched

Type guard

func isValidationErrors(err error) bool {
	var ve validator.ValidationErrors
	return errors.As(err, &ve)
}

Try / catch

if err := validate.Struct(req); err != nil {
	if isValidationErrors(err) {
		return ValidationErrorResponse(err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling ValidationErrorResponse with an error produced by something other than the validator library's Struct()/Validate() call — e.g. wrapping the error in fmt.Errorf before passing it, or passing a gRPC/transport error.

Common situations: Developers wrap or translate validation errors upstream (losing the concrete type) then pass the result to ValidationErrorResponse in addToCartHandler, placeOrderHandler, or setCurrencyHandler; refactors replacing validator with another library while keeping this helper.

Related errors


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