go-playground/validator · critical
Undefined validation function '%s' on field '%s'
Error message
Undefined validation function '%s' on field '%s'
What it means
This panic occurs during struct tag parsing (cache.go:311) when a validation tag used on a struct field is not registered in the validator's tag registry and is not a known alias. The library compiles tags into cached execution plans the first time a type is validated; any unknown tag name hits the else branch and panics with `undefinedValidation`. It is a fail-fast panic because an unrecognized tag means the validation expression cannot be compiled.
Source
Thrown at cache.go:311
aliasFirst, aliasLast := v.parseFieldTagsRecursive(aliasTag, fieldName, current.tag, true)
current.tag = aliasFirst.tag
current.fn = aliasFirst.fn
current.runValidationWhenNil = aliasFirst.runValidationWhenNil
current.hasParam = aliasFirst.hasParam
current.param = aliasFirst.param
current.typeof = aliasFirst.typeof
current.hasAlias = true
if aliasFirst.next != nil {
nextInChain := current.next
current.next = aliasFirst.next
aliasLast.next = nextInChain
aliasLast.isBlockEnd = false
current = aliasLast
}
} else {
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName)))
}
if len(orVals) > 1 {
current.typeof = typeOr
}
if len(vals) > 1 {
current.param = strings.ReplaceAll(strings.ReplaceAll(vals[1], utf8HexComma, ","), utf8Pipe, "|")
}
}
current.isBlockEnd = true
}
}
return
}
func (v *Validate) fetchCacheTag(tag string) *cTag {
// find cached tagView on GitHub (pinned to facf128d2e)
Solutions
- Fix the tag spelling on the offending struct field so it matches a baked-in validator (required, email, min, oneof, etc.).
- Register the custom function before validating: v.RegisterValidation("mytag", myFunc) — do this for every Validate instance you create.
- If using shorthand, call v.RegisterAlias(alias, tags) before validation.
- Check whether the tag was renamed in a validator/v10 upgrade by consulting the README tag table.
- Find the failing field from the panic message ('on field %s') and inspect its tag at that struct location.
Example fix
// before
type User struct {
Email string `validate:"required,emial"` // typo
}
// after
type User struct {
Email string `validate:"required,email"`
}
// or for a custom tag:
// v.RegisterValidation("mytag", myFunc) before v.Struct(user) Defensive patterns
Strategy: validation
Validate before calling
func checkTags(v *validator.Validate, samples ...interface{}) {
for _, s := range samples {
defer func() {
if r := recover(); r != nil {
panic(fmt.Sprintf("bad tag at startup: %v", r))
}
}()
_ = v.Struct(s) // exercise each type once at boot
}
} Try / catch
func safeValidate(v *validator.Validate, s interface{}) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("tag configuration panic: %v", r)
}
}()
return v.Struct(s)
} Prevention
- Register every custom validator and alias in package init on every Validate instance.
- Keep a startup test that validates one instance of each annotated struct.
- Verify tag names against the README tag table when upgrading validator/v10.
- Use an editor plugin or linter that flags unknown struct tag names.
When it happens
Trigger: Calling validate.Struct() (or Var) on a struct whose tag references a misspelled or non-existent validator (e.g. `validate:"required,emial"`); using a custom validator tag without calling RegisterValidation first; using an alias without RegisterAlias; a typo introduced by refactoring tags; passing a tag containing a stray character that splits it into an unknown tag.
Common situations: Typo in a struct tag; forgetting to register a custom validator on a newly created Validate instance (a second instance that lacks registrations the first had); upgrading validator/v10 where a tag was renamed or removed; copying tags between projects where custom tags were registered in package init; defining an alias that itself expands to an unknown tag.
Related errors
- Bad param number for required_if %s
- Duplicate param %s for required_if %s
- Bad param number for excluded_if %s
- Bad param number for required_unless %s
- Bad param number for skip_unless %s
AI-assisted analysis of go-playground/validator@facf128d2e (2026-09-02).
Data as JSON: /api/errors/0e77062a66b7bb4a.
Report an issue: GitHub.