go-playground/validator · error
Tag '%s' either contains restricted characters or is the sam
Error message
Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation
What it means
validator_instance.go:754 panics in registerValidation when a non-baked-in custom tag name is already in restrictedTags or contains restrictedTagChars ('-', '=', etc.). Just like RegisterAlias, custom validator names must not collide with built-in tags or contain tag-grammar characters, because that would corrupt tag parsing. Note the same function returns an error (not a panic) when fn is nil — the panic is specific to the tag name.
Source
Thrown at validator_instance.go:754
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}
func (v *Validate) registerValidation(tag string, fn FuncCtx, bakedIn bool, nilCheckable bool) error {
if len(tag) == 0 {
return errors.New("function Key cannot be empty")
}
if fn == nil {
return errors.New("function cannot be empty")
}
_, ok := restrictedTags[tag]
if !bakedIn && (ok || strings.ContainsAny(tag, restrictedTagChars)) {
panic(fmt.Sprintf(restrictedTagErr, tag))
}
v.validations[tag] = internalValidationFuncWrapper{fn: fn, runValidationOnNil: nilCheckable}
return nil
}
View on GitHub (pinned to facf128d2e)
Solutions
- Choose a custom tag name that is not in the restrictedTags denylist and contains only safe characters (letters, digits, underscore).
- If you need different behavior than a baked-in tag, register it under a new name and use that name in your struct tags.
- Sanitize/validate dynamic tag names before calling RegisterValidation (reject names containing '-', '=', '.', ',', '|').
- For nil-function mistakes, check fn != nil before registering — that path returns an error rather than panicking but is easy to conflate.
- Register all custom validators in package init at startup so panics are caught at boot.
Example fix
// before
v.RegisterValidation("my-validator", myFunc) // '-' restricted
v.RegisterValidation("email", overrideEmail) // restricted tag
// after
v.RegisterValidation("myValidator", myFunc)
v.RegisterValidation("customEmail", overrideEmail) Defensive patterns
Strategy: validation
Validate before calling
func safeRegisterValidation(v *validator.Validate, tag string, fn validator.FuncCtx) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("invalid tag %q: %v", tag, r)
}
}()
return v.RegisterValidationCtx(tag, fn)
} Type guard
var validTagRe = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`)
func isSafeCustomTag(tag string) bool {
return validTagRe.MatchString(tag)
} Try / catch
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("RegisterValidation rejected %q: %v", tag, r)
}
}()
err = v.RegisterValidation(tag, fn) Prevention
- Use letters, digits, underscore for custom tag names; reject names containing '-', '=', '.', ',', '|'.
- Never register a name that matches a baked-in tag; check restrictedTags first.
- Sanitize user/config-supplied tag names before registration.
- Register all custom validators at startup and add a boot-time test.
When it happens
Trigger: v.RegisterValidation("required", myFunc) — re-registering a restricted built-in name; v.RegisterValidation("my-func", fn) with a dash or other restrictedTagChars in the name; wrapping RegisterValidation with dynamically built tag names that include restricted characters; attempting to override email/uuid with custom logic.
Common situations: Teams trying to override baked-in validators (upgrade path from older validator versions that allowed it); naming custom validators with kebab-case; user-supplied or config-driven tag names passed straight to RegisterValidation; copy-pasted registration code where someone renamed the tag adding separators.
Related errors
- Alias '%s' either contains restricted characters or is the s
- Bad field type %T
- panic(err) (os.Stat *PathError re-raised for unexpected stat
- Bad param number for required_if %s
- Duplicate param %s for required_if %s
AI-assisted analysis of go-playground/validator@facf128d2e (2026-09-02).
Data as JSON: /api/errors/53b37ada418f8999.
Report an issue: GitHub.