caddyserver/caddy · error

no handlers defined

Error message

no handlers defined

What it means

In the events app, a subscription with a non-nil HandlersRaw that loads to zero handlers is rejected: binding a subscription with no handlers would be pointless work. Provision fails immediately rather than silently ignoring the subscription.

Source

Thrown at modules/caddyevents/app.go:137

// Provision sets up the app.
func (app *App) Provision(ctx caddy.Context) error {
	app.logger = ctx.Logger()
	app.subscriptions = make(map[string]map[caddy.ModuleID][]Handler)

	for _, sub := range app.Subscriptions {
		if sub.HandlersRaw == nil {
			continue
		}
		handlersIface, err := ctx.LoadModule(sub, "HandlersRaw")
		if err != nil {
			return fmt.Errorf("loading event subscriber modules: %v", err)
		}
		for _, h := range handlersIface.([]any) {
			sub.Handlers = append(sub.Handlers, h.(Handler))
		}
		if len(sub.Handlers) == 0 {
			// pointless to bind without any handlers
			return fmt.Errorf("no handlers defined")
		}
	}

	return nil
}

// Start runs the app.
func (app *App) Start() error {
	for _, sub := range app.Subscriptions {
		if err := app.Subscribe(sub); err != nil {
			return err
		}
	}

	app.started = true

	return nil
}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Add at least one handler inside the subscription block, or
  2. Delete the whole subscription block if it is no longer needed.
  3. Guard templating so empty-handler subscriptions are omitted entirely rather than emitted empty.

Example fix

// before (caddyfile)
{
    events {
        on tls cert_obtained {}
    }
}

// after
{
    events {
        on tls cert_obtained {
            handler exec {
                command echo obtained
            }
        }
    }
}
Defensive patterns

Strategy: validation

Validate before calling

// templating guard: emit subscription only when handlers exist
{{if .Handlers}}
{
    events {
        on {{.Event}} {
            {{range .Handlers}}handler {{.}}
            {{end}}
        }
    }
}
{{end}}

Try / catch

if err := caddy.Validate(cfg); err != nil {
    if strings.Contains(err.Error(), "no handlers defined") {
        // delete the empty subscription or add a handler, then re-validate
    }
    return err
}

Prevention

When it happens

Trigger: An events subscription whose handlers array is present but empty: Caddyfile 'on <event> {}' with nothing inside, or JSON "handlers": [].

Common situations: Templated configs that render an empty handlers list when a variable is empty; commented-out handlers leaving an empty block; incremental edits where the handler was deleted but the subscription shell remained.

Related errors


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