caddyserver/caddy · error
matcher module '%s' is not a request matcher
Error message
matcher module '%s' is not a request matcher
What it means
While parsing Caddyfile named-matcher definitions (parseMatcherDefinitions), each token is unmarshalled via its module's UnmarshalCaddyfile and then asserted to RequestMatcher/RequestMatcherWithError. A matcher name that resolves to a module not implementing those interfaces produces this error. This is the Caddyfile-adaptation path, so it surfaces at `caddy adapt`/`validate` time.
Source
Thrown at modules/caddyhttp/matchers.go:1720
return nil, d.Errf("getting matcher module '%s': %v", matcherName, err)
}
unm, ok := mod.New().(caddyfile.Unmarshaler)
if !ok {
return nil, d.Errf("matcher module '%s' is not a Caddyfile unmarshaler", matcherName)
}
err = unm.UnmarshalCaddyfile(caddyfile.NewDispenser(tokens))
if err != nil {
return nil, err
}
if rm, ok := unm.(RequestMatcherWithError); ok {
matcherMap[matcherName] = rm
continue
}
if rm, ok := unm.(RequestMatcher); ok {
matcherMap[matcherName] = rm
continue
}
return nil, fmt.Errorf("matcher module '%s' is not a request matcher", matcherName)
}
// we should now have a functional matcher, but we also
// need to be able to marshal as JSON, otherwise config
// adaptation will be missing the matchers!
matcherSet := make(caddy.ModuleMap)
for name, matcher := range matcherMap {
jsonBytes, err := json.Marshal(matcher)
if err != nil {
return nil, fmt.Errorf("marshaling %T matcher: %v", matcher, err)
}
matcherSet[name] = jsonBytes
}
return matcherSet, nil
}
var wordRE = regexp.MustCompile(`\w+`)View on GitHub (pinned to 50e54ee279)
Solutions
- Correct the matcher token to a real request matcher (path, host, method, header, query, path_regexp, ...).
- If it comes from a plugin, ensure the plugin type implements RequestMatcher/RequestMatcherWithError and is registered under http.matchers.*.
- Run `caddy adapt --pretty --config Caddyfile` to localize the failing token.
Example fix
// before (Caddyfile) @m path_regexpx ^/api // after @m path_regexp ^/api
Defensive patterns
Strategy: type-guard
Type guard
// Verify a module instance is usable as a Caddyfile named matcher
func isRequestMatcher(mod caddy.Module) bool {
if _, ok := mod.(caddyhttp.RequestMatcherWithError); ok {
return true
}
_, ok := mod.(caddyhttp.RequestMatcher)
return ok
} Prevention
- Spell matcher tokens exactly (path_regexp, header_regexp, query_regexp).
- Run `caddy adapt --pretty` to localize failing tokens early.
- Keep plugins in the build; missing modules surface here.
When it happens
Trigger: Writing @m not { ... } style nested tokens incorrectly, using an undefined/misspelled matcher name inside a named matcher, or a third-party plugin registering under http.matchers.* a type that is not a request matcher.
Common situations: Typos in matcher names (`path_regexpx`); plugins built against an old Caddy API where the module was a handler but named like a matcher; custom forks with namespace mistakes.
Related errors
- matcher module '%s' is not a Caddyfile unmarshaler
- matcher module '%s' is not a request matcher
- marshaling matcher set %#v: %v
- module is not a request matcher: %T
- marshaling %T matcher: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/4d2db22aced5ab0e.
Report an issue: GitHub.