go-playground/validator · critical
'endkeys' tag encountered without a corresponding 'keys' tag
Error message
'endkeys' tag encountered without a corresponding 'keys' tag
What it means
An `endkeys` tag was parsed without a matching `keys` tag in the same tag chain. cache.go panics with keysTagNotDefined ("'endkeys' tag encountered without a corresponding 'keys' tag") when `endkeys` appears where no keys block is open (specifically when it is not the terminating tag after a keys block).
Source
Thrown at cache.go:242
for ; i < len(tags); i++ {
b = append(b, tags[i]...)
b = append(b, ',')
if tags[i] == endKeysTag {
break
}
}
current.keys, _ = v.parseFieldTagsRecursive(string(b[:len(b)-1]), fieldName, "", false)
case endKeysTag:
current.typeof = typeEndKeys
// if there are more in tags then there was no keysTag defined
// and an error should be thrown
if i != len(tags)-1 {
panic(keysTagNotDefined)
}
return
case omitzero:
current.typeof = typeOmitZero
continue
case omitempty:
current.typeof = typeOmitEmpty
case omitnil:
current.typeof = typeOmitNil
case structOnlyTag:
current.typeof = typeStructOnly
case noStructLevelTag:
current.typeof = typeNoStructLevelView on GitHub (pinned to facf128d2e)
Solutions
- Ensure every `endkeys` is preceded by `keys` inside a `dive` block: `dive,keys,<...>,endkeys,<...>`
- Remove the orphaned `endkeys` tag
- Fix generated/aliased tag strings to emit the full keys/endkeys pair
- Validate a sample struct in unit tests to catch syntax panics at build time
Example fix
// before M map[string]string `validate:"dive,endkeys,min=1"` // after M map[string]string `validate:"dive,keys,min=1,endkeys,min=1"`
Defensive patterns
Strategy: validation
Validate before calling
func checkEndKeys(t reflect.StructTag) error {
tags := strings.Split(t.Get("validate"), ",")
depth := 0
for _, tg := range tags {
switch tg {
case "keys": depth++
case "endkeys":
if depth == 0 { return errors.New("endkeys without keys") }
depth--
}
}
return nil
} Try / catch
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("invalid tag structure: %v", r)
}
}()
_ = validate.Struct(sample) Prevention
- Pair every endkeys with a keys inside a dive block
- Delete keys and endkeys together during refactors
- Add tag-pair linting to CI
- Validate a fixture struct per type at init
When it happens
Trigger: Tag like `validate:"dive,endkeys,required"` or `validate:"endkeys"` — endkeys without keys; also endkeys followed by more tags but no preceding keys.
Common situations: Deleting a `keys,...` segment during editing while leaving `endkeys`; misunderstanding of the dive,keys,endkeys pairing for map validation.
Related errors
- '%s' tag must be immediately preceded by the '%s' tag
- Invalid validation tag on field '%s'
- Bad field type %T
- panic(err) (os.Stat *PathError re-raised for unexpected stat
- Bad param number for required_if %s
AI-assisted analysis of go-playground/validator@facf128d2e (2026-09-02).
Data as JSON: /api/errors/76f69be995b38587.
Report an issue: GitHub.