caddyserver/caddy · error
loading config loader module: %s
Error message
loading config loader module: %s
What it means
Thrown when the Admin.Config.LoadRaw module cannot be loaded via ctx.LoadModule. The dynamic config loader module (anything implementing ConfigLoader registered under the config load namespace) failed to provision or its raw JSON could not be decoded into the module.
Source
Thrown at caddy.go:614
// so that cert management of this endpoint doesn't prevent user's
// servers from starting which likely also use HTTP/HTTPS ports;
// but before remote management which may depend on these creds)
err := manageIdentity(ctx, cfg)
if err != nil {
return fmt.Errorf("provisioning remote admin endpoint: %v", err)
}
// replace any remote admin endpoint
err = replaceRemoteAdminServer(ctx, cfg)
if err != nil {
return fmt.Errorf("provisioning remote admin endpoint: %v", err)
}
// if dynamic config is requested, set that up and run it
if cfg != nil && cfg.Admin != nil && cfg.Admin.Config != nil && cfg.Admin.Config.LoadRaw != nil {
val, err := ctx.LoadModule(cfg.Admin.Config, "LoadRaw")
if err != nil {
return fmt.Errorf("loading config loader module: %s", err)
}
logger := Log().Named("config_loader").With(
zap.String("module", val.(Module).CaddyModule().ID.Name()),
zap.Int("load_delay", int(cfg.Admin.Config.LoadDelay)))
runLoadedConfig := func(config []byte) error {
logger.Info("applying dynamically-loaded config")
err := changeConfig(http.MethodPost, "/"+rawConfigKey, config, "", false)
if errors.Is(err, errSameConfig) {
return err
}
if err != nil {
logger.Error("failed to run dynamically-loaded config", zap.Error(err))
return err
}
logger.Info("successfully applied dynamically-loaded config")
return nilView on GitHub (pinned to 50e54ee279)
Solutions
- Check the wrapped error: 'unknown module' means the loader is missing from the build; rebuild with the correct plugin
- Validate the admin.config.load JSON object against the loader module's expected schema
- If a custom loader, test its Provision() independently (e.g. via caddy adapt + unit tests)
- Remove admin.config temporarily to isolate whether the rest of the config is valid
Example fix
// before (module not in build)
{"admin": {"config": {"load": {"myloader": {}}}}}
// after (use a loader compiled in, e.g. http)
{"admin": {"config": {"load": {"http": {"url": "http://cfg.internal/current"}}}}} Defensive patterns
Strategy: validation
Validate before calling
// confirm the loader module exists in this build before running
name := "http" // module name under config loaders
if _, found := caddy.GetModule("caddy.config_loaders." + name); ! found {
return fmt.Errorf("loader %q not compiled in", name)
} Prevention
- Pin and test custom builds that include config loader plugins
- Validate admin.config.load JSON with `caddy validate --adapter json`
- Unit-test custom loader Provision() methods
When it happens
Trigger: cfg.Admin.Config.LoadRaw is non-nil (dynamic config requested) and ctx.LoadModule(cfg.Admin.Config, "LoadRaw") returns an error: unknown module name, invalid inline JSON for the loader, or the loader's Provision() failing.
Common situations: A config JSON with admin.config.load referencing a module that is not compiled into the custom Caddy build, or with malformed loader arguments. Also occurs when a third-party loader module panics/errors during provisioning.
Related errors
- loading dynamic config from %T: %v
- --config is required
- provisioning admin router module %s: %v
- loading identity issuer modules: %s
- no server identity configured
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/9e9e47fedc31db27.
Report an issue: GitHub.