caddyserver/caddy · error
loading handler modules: %v
Error message
loading handler modules: %v
What it means
Route.ProvisionHandlers loads the handler chain for a route via ctx.LoadModule; this error wraps any failure to instantiate/provision a handler. Causes include unknown handler module IDs, wrong JSON shape for a handler, or a handler plugin absent from the binary.
Source
Thrown at modules/caddyhttp/routes.go:163
matchersIface, err := ctx.LoadModule(r, "MatcherSetsRaw")
if err != nil {
return fmt.Errorf("loading matcher modules: %v", err)
}
err = r.MatcherSets.FromInterface(matchersIface)
if err != nil {
return err
}
return nil
}
// ProvisionHandlers sets up all the handlers by loading the
// handler modules. Only call this method directly if you need
// to set up matchers and handlers separately without having
// to provision a second time; otherwise use Provision instead.
func (r *Route) ProvisionHandlers(ctx caddy.Context, metrics *Metrics) error {
handlersIface, err := ctx.LoadModule(r, "HandlersRaw")
if err != nil {
return fmt.Errorf("loading handler modules: %v", err)
}
for _, handler := range handlersIface.([]any) {
r.Handlers = append(r.Handlers, handler.(MiddlewareHandler))
}
// Store metrics info for route-level instrumentation (applied once
// per route in wrapRoute, instead of per-handler which was redundant).
r.metrics = metrics
r.metricsCtx = ctx
if len(r.Handlers) > 0 {
r.handlerName = caddy.GetModuleName(r.Handlers[0])
}
// Make ProvisionHandlers idempotent by clearing the middleware field
r.middleware = []Middleware{}
// pre-compile the middleware handler chain
for _, midhandler := range r.Handlers {View on GitHub (pinned to 50e54ee279)
Solutions
- Inspect the wrapped error for the exact module and reason
- Run 'caddy list-modules --packages http.handlers' to confirm the handler exists in this build
- Correct the handler name/fields in the route
- Rebuild with xcaddy if the handler comes from a plugin
Example fix
// before
"handle": [{ "handler": "reverse_proxy", "upstream": "localhost:8080" }]
// after
"handle": [{ "handler": "reverse_proxy", "upstreams": [{ "dial": "localhost:8080" }] }] Defensive patterns
Strategy: validation
Validate before calling
// CLI check before deploy:
// caddy validate --config Caddyfile
// caddy list-modules --packages http.handlers
// library: ensure each handler name is registered
for _, h := range route.HandlersRaw {
name, _ := h.(map[string]any) // first key is module name
for k := range name {
if !knownHandlers[k] { return fmt.Errorf("unknown handler %q", k) }
}
} Prevention
- Validate config with the same binary that will serve it
- When removing a plugin from an xcaddy build, grep configs for its handler ID
- Adapt Caddyfile to JSON and schema-check before applying
When it happens
Trigger: A route whose "handle" array references "http.handlers.fil_server" (typo), passes a string where a number is expected, or uses a third-party handler not compiled in.
Common situations: Hand-written JSON configs, moving a config from an xcaddy build to a standard caddy binary, or upgrading Caddy where a handler's config schema changed.
Related errors
- loading matcher modules: %v
- server %s: setting up route handlers: %v
- invoke: route '%s' not found
- route %d: %v
- loading certificate loader modules: %s
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/ec142ec5d08913cf.
Report an issue: GitHub.