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

  1. Inspect the wrapped error for the exact module and reason
  2. Run 'caddy list-modules --packages http.handlers' to confirm the handler exists in this build
  3. Correct the handler name/fields in the route
  4. 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

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


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