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
- Read the suffixed inner error — fix the nested matcher it describes, not the `not` itself.
- Test the inner matcher standalone (without `not`) to reproduce the underlying error directly.
- 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
- Treat 'loading matcher sets:' as a wrapper — always read the suffixed cause.
- Test the inner matcher without `not` to isolate failures.
- Keep custom matcher plugins loaded in the binary.
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
- unsupported map key type in header match: %T
- unknown try policy %s
- compiling matcher regexp %s: %v
- unknown object ID '%s'
- decoding request body: %w, at offset %d
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/430d12c83c5b0f04.
Report an issue: GitHub.