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 nil

View on GitHub (pinned to 50e54ee279)

Solutions

  1. 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, ...).
  2. If the matcher comes from a plugin, verify it is in the build: 'caddy list-modules' and look under http.matchers.
  3. Rebuild with 'xcaddy build --with <plugin-module-path>' and retry adapt/run.
  4. 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

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


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/834abecefbb1fbc0. Report an issue: GitHub.