caddyserver/caddy · error

loading certificate loader modules

Error message

loading certificate loader modules: %s

What it means

Thrown when ctx.LoadModule(t, "CertificatesRaw") fails while provisioning the tls app's 'certificates' section. CertificatesRaw is a map of loader-name -> module config (loaders such as load_files, load_folders, automate). The load fails for any entry whose module name is unknown, whose inline JSON is malformed for the loader, or whose own Provision returns an error.

Solutions

  1. Inspect the wrapped error: it names which loader entry failed and why
  2. Use 'caddy adapt' (or 'caddy validate --config ... --adapter ...') to confirm the config adapts and the loader names match the docs (load_files, load_folders, automate)
  3. Ensure each load_files entry has both 'certificate' and 'key' string fields with valid paths
  4. For custom loaders, verify the module is registered via 'caddy list-modules'

Example fix

// before
{"apps": {"tls": {"certificates": {"load_file": [{"certificate": "/certs/a.pem", "key": "/certs/a.key"}]}}}}
// after
{"apps": {"tls": {"certificates": {"load_files": [{"certificate": "/certs/a.pem", "key": "/certs/a.key"}]}}}}
Defensive patterns

Strategy: validation

Validate before calling

caddy adapt --config Caddyfile --adapter caddyfile --pretty | jq '.apps.tls.certificates'
# confirm only known loader keys: load_files, load_folders, automate

Prevention

When it happens

Trigger: Configuring tls.certificates with an invalid loader key, e.g. {"certificates": {"load_file": [...]}} (singular, nonexistent) instead of "load_files"; wrong array/object shape for load_files entries (missing 'certificate'/'key' fields); a custom loader module not compiled in.

Common situations: Hand-written JSON configs with typos in loader names; Caddyfile 'tls /path/cert.pem /path/key.pem' translating to load_files with unreadable or misquoted paths; migrating configs between Caddy versions where loader schemas changed.

Understand the failure class

Related errors


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

Appendix: source

Thrown at modules/caddytls/tls.go:225

	if t.Cache != nil {
		cacheOpts.Capacity = t.Cache.Capacity
	}
	if cacheOpts.Capacity <= 0 {
		cacheOpts.Capacity = 10000
	}

	certCacheMu.Lock()
	if certCache == nil {
		certCache = certmagic.NewCache(cacheOpts)
	} else {
		certCache.SetOptions(cacheOpts)
	}
	certCacheMu.Unlock()

	// certificate loaders
	val, err := ctx.LoadModule(t, "CertificatesRaw")
	if err != nil {
		return fmt.Errorf("loading certificate loader modules: %s", err)
	}
	for modName, modIface := range val.(map[string]any) {
		if modName == "automate" {
			// special case; these will be loaded in later using our automation facilities,
			// which we want to avoid doing during provisioning
			if automateNames, ok := modIface.(*AutomateLoader); ok && automateNames != nil {
				if t.automateNames == nil {
					t.automateNames = make(map[string]struct{})
				}
				repl := caddy.NewReplacer()
				for _, sub := range *automateNames {
					t.automateNames[repl.ReplaceAll(sub, "")] = struct{}{}
				}
			} else {
				return fmt.Errorf("loading certificates with 'automate' requires array of strings, got: %T", modIface)
			}
			continue
		}

View on GitHub (pinned to 50e54ee279)