caddyserver/caddy · error
getting matcher module '%s': %v
Error message
getting matcher module '%s': %v
What it means
Thrown while adapting a Caddyfile when a named matcher definition (e.g. '@mymatch { ... }') references a matcher module that is not registered under the 'http.matchers.' namespace. caddy.GetModule fails, so the adapter cannot instantiate the matcher. This almost always means the matcher name is misspelled or the build does not include the plugin providing that matcher.
Source
Thrown at caddyconfig/httpcaddyfile/httptype.go:1695
if _, ok := matchers[definitionName]; ok {
return fmt.Errorf("matcher is defined more than once: %s", definitionName)
}
matchers[definitionName] = make(caddy.ModuleMap)
// given a matcher name and the tokens following it, parse
// the tokens as a matcher module and record it
makeMatcher := func(matcherName string, tokens []caddyfile.Token) error {
// create a new dispenser from the tokens
dispenser := caddyfile.NewDispenser(tokens)
// set the matcher name (without @) in the dispenser context so
// that matcher modules can access it to use it as their name
// (e.g. regexp matchers which use the name for capture groups)
dispenser.SetContext(caddyfile.MatcherNameCtxKey, definitionName[1:])
mod, err := caddy.GetModule("http.matchers." + matcherName)
if err != nil {
return fmt.Errorf("getting matcher module '%s': %v", matcherName, err)
}
unm, ok := mod.New().(caddyfile.Unmarshaler)
if !ok {
return fmt.Errorf("matcher module '%s' is not a Caddyfile unmarshaler", matcherName)
}
err = unm.UnmarshalCaddyfile(dispenser)
if err != nil {
return err
}
if rm, ok := unm.(caddyhttp.RequestMatcherWithError); ok {
matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil)
return nil
}
// nolint:staticcheck
if rm, ok := unm.(caddyhttp.RequestMatcher); ok {
matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil)
return nilView on GitHub (pinned to 50e54ee279)
Solutions
- Check the exact spelling of the matcher name against the Caddyfile matcher docs (header, header_regexp, path, path_regexp, method, query, expression, remote_ip, client_ip, protocol, file, not, vars, ...).
- If the matcher comes from a plugin, verify it is in the build: 'caddy list-modules' and look under http.matchers.
- Rebuild with 'xcaddy build --with <plugin-module-path>' and retry adapt/run.
- If upgrading, read the plugin's changelog for matcher renames and update the Caddyfile.
Example fix
# before @api path_regex ^/api/(.*) # after @api path_regexp ^/api/(.*)
Defensive patterns
Strategy: validation
Validate before calling
# before adapting/running, confirm the matcher is registered caddy list-modules 2>/dev/null | grep -q '^http.matchers.header_regexp$' && echo ok || echo 'matcher missing from build'
Prevention
- Run 'caddy adapt --config Caddyfile --adapter caddyfile' in CI to catch adapt-time errors before deploy.
- Pin plugin versions and rebuild the whole binary with xcaddy whenever core is upgraded.
- Keep a checked-in list of required plugins next to the Caddyfile.
When it happens
Trigger: Writing '@myMatcher header_regexp ...' with a typo like '@myMatcher header_regex ...'; using a matcher provided by a third-party plugin in a binary built without that plugin; referencing an experimental matcher renamed between Caddy versions.
Common situations: Custom/xcaddy builds where a plugin was dropped from the build list; upgrading Caddy without rebuilding plugins; Caddyfiles copied from docs of a plugin the user never installed; typo in a matcher name inside a named matcher block.
Related errors
- matcher module '%s' is not a Caddyfile unmarshaler
- matcher module '%s' is not a request matcher
- marshaling matcher set %#v: %v
- matcher module '%s' is not a request matcher
- unable to parse URL pattern: %w
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/834abecefbb1fbc0.
Report an issue: GitHub.