caddyserver/caddy · error

loading matcher sets: %v

Error message

loading matcher sets: %v

What it means

MatchNot.Provision loads the raw nested matcher sets under a `not` directive via ctx.LoadModule. Any failure while instantiating a nested matcher (bad arguments, unknown module, its own provisioning error) is wrapped as "loading matcher sets: %v". The real cause is in the chained error text.

Source

Thrown at modules/caddyhttp/matchers.go:1522

}

// UnmarshalJSON satisfies json.Unmarshaler. It puts the JSON
// bytes directly into m's MatcherSetsRaw field.
func (m *MatchNot) UnmarshalJSON(data []byte) error {
	return json.Unmarshal(data, &m.MatcherSetsRaw)
}

// MarshalJSON satisfies json.Marshaler by marshaling
// m's raw matcher sets.
func (m MatchNot) MarshalJSON() ([]byte, error) {
	return json.Marshal(m.MatcherSetsRaw)
}

// Provision loads the matcher modules to be negated.
func (m *MatchNot) Provision(ctx caddy.Context) error {
	matcherSets, err := ctx.LoadModule(m, "MatcherSetsRaw")
	if err != nil {
		return fmt.Errorf("loading matcher sets: %v", err)
	}
	for _, modMap := range matcherSets.([]map[string]any) {
		var ms MatcherSet
		for _, modIface := range modMap {
			if mod, ok := modIface.(RequestMatcherWithError); ok {
				ms = append(ms, mod)
				continue
			}
			if mod, ok := modIface.(RequestMatcher); ok {
				ms = append(ms, mod)
				continue
			}
			return fmt.Errorf("module is not a request matcher: %T", modIface)
		}
		m.MatcherSets = append(m.MatcherSets, ms)
	}
	return nil
}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Read the suffixed inner error — fix the nested matcher it describes, not the `not` itself.
  2. Test the inner matcher standalone (without `not`) to reproduce the underlying error directly.
  3. For missing plugins, rebuild Caddy with the plugin imported or remove the matcher.

Example fix

// before (Caddyfile)
@ok not path_regexp [bad

// after
@ok not path_regexp ^/private/.*
Defensive patterns

Strategy: try-catch

Try / catch

// In Go, handle the wrapped chain and surface the inner cause
if err := notMatcher.Provision(ctx); err != nil {
	inner := errors.Unwrap(err)
	if inner != nil {
		log.Printf("not matcher failed because of nested matcher: %v", inner)
	}
	return err
}

Prevention

When it happens

Trigger: `not` wrapping a matcher that itself fails provisioning, e.g. not path_regexp "[bad", not remote_ip 1.2.3.4/99, or a JSON `not` block referencing an unregistered custom matcher module.

Common situations: Complex negated matchers where the inner error is mistaken for a problem with `not`; third-party matcher plugins missing from the build; JSON configs with wrong field types inside `not`.

Related errors


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