projectdiscovery/nuclei · error
matcher %s has unexpected fields: %s
Error message
matcher %s has unexpected fields: %s
What it means
Template validation error from Matcher.Validate -> checkFields (pkg/operators/matchers/validate.go:81). The matcher is marshaled to a map, and every YAML key is mapped back to a struct field via getFieldNameFromYamlTag; keys not in the expected field set for the matcher's type (validate.go:35-51, e.g. word: Words/Part/Encoding/CaseInsensitive + common fields) are reported as unexpected, comma-separated. This catches fields misplaced under the wrong matcher type.
Source
Thrown at pkg/operators/matchers/validate.go:81
}
}
return nil
}
func checkFields(m *Matcher, matcherMap map[string]interface{}, expectedFields ...string) error {
var foundUnexpectedFields []string
for marshaledFieldName := range matcherMap {
// revert back the marshaled name to the original field
structFieldName, err := getFieldNameFromYamlTag(marshaledFieldName, *m)
if err != nil {
return err
}
if !sliceutil.Contains(expectedFields, structFieldName) {
foundUnexpectedFields = append(foundUnexpectedFields, structFieldName)
}
}
if len(foundUnexpectedFields) > 0 {
return fmt.Errorf("matcher %s has unexpected fields: %s", m.matcherType, strings.Join(foundUnexpectedFields, ","))
}
return nil
}
func getFieldNameFromYamlTag(tagName string, object interface{}) (string, error) {
reflectType := reflect.TypeOf(object)
if reflectType.Kind() != reflect.Struct {
return "", errors.New("the object must be a struct")
}
for idx := 0; idx < reflectType.NumField(); idx++ {
field := reflectType.Field(idx)
tagParts := strings.Split(field.Tag.Get("yaml"), ",")
if len(tagParts) > 0 && tagParts[0] == tagName {
return field.Name, nil
}
}
return "", fmt.Errorf("field %s not found", tagName)
}View on GitHub (pinned to 265b3a3dec)
Solutions
- Keep only fields valid for the matcher type (word: words/part/encoding/case-insensitive; regex: regex/part/...; status: status; size: size; dsl: dsl; binary: binary/part/encoding)
- Split mixed concerns into multiple matchers joined by condition instead of one matcher with foreign fields
- Validate with `nuclei -validate -t template.yaml` which surfaces the full unexpected-field list
- When generating templates programmatically, build typed structs instead of loose maps
Example fix
# before
matchers:
- type: status
status:
- 200
words:
- 'ok'
# after
matchers:
- type: status
status:
- 200
- type: word
words:
- 'ok' Defensive patterns
Strategy: validation
Validate before calling
allowed := map[string][]string{
"word": {"words", "part", "encoding", "case-insensitive", "condition", "match-all", "name", "internal"},
"status": {"status", "part"},
"size": {"size", "part"},
"regex": {"regex", "part", "encoding", "case-insensitive", "condition"},
"binary": {"binary", "part", "encoding"},
"dsl": {"dsl", "condition"},
"xpath": {"xpath", "part"},
}
// reject matcher maps containing keys outside allowed[type] Type guard
func matcherKeysValid(t string, keys []string) bool {
set := allowed[t]
for _, k := range keys { if !contains(set, k) { return false } }
return true
} Try / catch
if err := m.CompileMatchers(); err != nil {
if ve, ok := m.Validate(); ok == false && strings.Contains(ve.Error(), "unexpected fields") {
// list allowed fields for the matcher type in the error output
}
} Prevention
- One matcher, one type, only its own fields
- Split multi-signal detections into multiple matchers with condition: and
- Use -validate in CI to catch leftover fields after type changes
When it happens
Trigger: E.g. `type: status` with a `words:` list, `type: word` with `regex:` entries, or any key the Matcher struct does define but that type does not accept (also honors unknown keys that fail tag mapping). Note the loop returns early on a totally unknown key via getFieldNameFromYamlTag's error path.
Common situations: Copy-paste between matchers of different types without pruning the old field; tutorials mixing matcher fields; refactors that change type but leave stale keys; YAML anchors merging extra keys into a matcher.
Related errors
- unknown matcher type specified: %s
- unknown extractor type specified: %s
- unknown condition specified: %s
- case-insensitive flag is supported only for 'word' matchers
- validation failed for these fields
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/4827917c9ef0e8e0.
Report an issue: GitHub.