{"record":{"id":"06dd00e5396f9261","repo":"GoogleCloudPlatform/microservices-demo","slug":"invalid-validation-error-format","errorCode":null,"errorMessage":"invalid validation error format","messagePattern":"invalid validation error format","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/frontend/validator/validator.go","lineNumber":76,"sourceCode":"\n// Implementations of the 'Payload' interface.\nfunc (ad *AddToCartPayload) Validate() error {\n\treturn validate.Struct(ad)\n}\n\nfunc (po *PlaceOrderPayload) Validate() error {\n\treturn validate.Struct(po)\n}\n\nfunc (sc *SetCurrencyPayload) Validate() error {\n\treturn validate.Struct(sc)\n}\n\n// Reusable error response function.\nfunc ValidationErrorResponse(err error) error {\n\tvalidationErrs, ok := err.(validator.ValidationErrors)\n\tif !ok {\n\t\treturn errors.New(\"invalid validation error format\")\n\t}\n\tvar msg string\n\tfor _, err := range validationErrs {\n\t\tmsg += fmt.Sprintf(\"Field '%s' is invalid: %s\\n\", err.Field(), err.Tag())\n\t}\n\treturn fmt.Errorf(\"%s\", msg)\n}\n","sourceCodeStart":58,"sourceCodeEnd":84,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/frontend/validator/validator.go#L58-L84","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass the raw error returned by validator.Struct(...) directly, without wrapping","Check the type before calling: only invoke ValidationErrorResponse when errors.As(err, &validator.ValidationErrors{})","Fix call sites (addToCartHandler, placeOrderHandler, setCurrencyHandler) that wrap the validator error","Log the original error to see what type actually arrived"],"exampleFix":"// before\nif err := validator.New().Struct(req); err != nil {\n    return ValidationErrorResponse(fmt.Errorf(\"cart error: %w\", err))\n}\n// after\nif err := validator.New().Struct(req); err != nil {\n    return ValidationErrorResponse(err) // pass unwrapped ValidationErrors\n}","handlingStrategy":"type-guard","validationCode":"var vErr validator.ValidationErrors\nif errors.As(err, &vErr) {\n\treturn ValidationErrorResponse(err) // safe: concrete type present\n}\nreturn err // pass through non-validator errors untouched","typeGuard":"func isValidationErrors(err error) bool {\n\tvar ve validator.ValidationErrors\n\treturn errors.As(err, &ve)\n}","tryCatchPattern":"if err := validate.Struct(req); err != nil {\n\tif isValidationErrors(err) {\n\t\treturn ValidationErrorResponse(err)\n\t}\n\treturn err\n}","preventionTips":["Never wrap validator errors with fmt.Errorf before passing to ValidationErrorResponse","Keep the raw return value of validator.Struct intact until formatting","Use errors.As to check the concrete type instead of assuming","Update this helper if the validator library is changed or upgraded"],"tags":["go","validation","type-assertion"],"backgroundTag":"invalid-validation-error-format","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}