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

  1. Correct the matcher token to a real request matcher (path, host, method, header, query, path_regexp, ...).
  2. If it comes from a plugin, ensure the plugin type implements RequestMatcher/RequestMatcherWithError and is registered under http.matchers.*.
  3. 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

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


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