caddyserver/caddy · error
loading TLS storage module: %v
Error message
loading TLS storage module: %v
What it means
The automation policy declares a storage module (StorageRaw, e.g. a custom certmagic storage backend) and caddy.Context.LoadModule failed to instantiate/provision it. The wrapped error carries the underlying module's own failure (bad module config, unknown module name, or the module's Provision error).
Source
Thrown at modules/caddytls/automation.go:200
func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
// replace placeholders in subjects to allow environment variables
repl := caddy.NewReplacer()
subjects := make([]string, len(ap.SubjectsRaw))
for i, sub := range ap.SubjectsRaw {
sub = repl.ReplaceAll(sub, "")
subASCII, err := idna.ToASCII(sub)
if err != nil {
return fmt.Errorf("could not convert automation policy subject '%s' to punycode: %v", sub, err)
}
subjects[i] = subASCII
}
ap.subjects = subjects
// policy-specific storage implementation
if ap.StorageRaw != nil {
val, err := tlsApp.ctx.LoadModule(ap, "StorageRaw")
if err != nil {
return fmt.Errorf("loading TLS storage module: %v", err)
}
cmStorage, err := val.(caddy.StorageConverter).CertMagicStorage()
if err != nil {
return fmt.Errorf("creating TLS storage configuration: %v", err)
}
ap.storage = cmStorage
}
// we don't store loaded modules directly in the certmagic config since
// policy provisioning may happen more than once (during auto-HTTPS) and
// loading a module clears its config bytes; thus, load the module and
// store them on the policy before putting it on the config
// load and provision any cert manager modules
if ap.ManagersRaw != nil {
ap.hadExplicitManagers = true
vals, err := tlsApp.ctx.LoadModule(ap, "ManagersRaw")
if err != nil {View on GitHub (pinned to 50e54ee279)
Solutions
- Read the wrapped error — it identifies which module failed and why; fix that module's configuration.
- If the module is unknown, build Caddy (xcaddy build --with ...) including the storage plugin, or remove the storage block to use default local storage.
- Verify credentials, endpoints, and permissions for the storage backend (e.g. S3 bucket write access).
- Test the storage config in isolation with the module's own tooling before wiring it into the automation policy.
Example fix
// before: plugin not compiled in
{"apps":{"tls":{"automation":{"policies":[{"subjects":["example.com"],"storage":{"module":"redis"}}]}}}}
// after: build with plugin, or use file_system storage
"storage": {"module": "file_system", "root": "/var/lib/caddy/storage"} Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the module is present before referencing it.
if caddy.GetModule("caddy.storage.redis") == nil { // pseudocode; iterate caddy.Modules()
return errors.New("storage plugin not compiled in; rebuild with xcaddy --with")
} Try / catch
if err := policy.Provision(tlsApp); err != nil {
if strings.Contains(err.Error(), "loading TLS storage module") {
return fmt.Errorf("fix or remove policy storage config: %w", err)
}
} Prevention
- Build custom binaries with xcaddy and pin plugin versions in a checked-in build script.
- Run `caddy validate --config Caddyfile --adapter caddyfile` in CI with the production binary.
- Keep storage module configs minimal and tested per environment.
When it happens
Trigger: Setting "storage" inside a TLS automation policy to a module name that is not compiled into the binary; a storage module whose Provision rejects its options (bad connection string, unwritable path); JSON type mismatches in the storage module config.
Common situations: Using a plugin storage backend (S3, Redis, Consul...) without having built Caddy with that plugin; typo'd module names in JSON config; wrong credentials/endpoints for the storage backend; version drift between plugin and Caddy.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- loading external certificate manager modules: %v
- loading TLS automation management module: %s
- loading TLS storage module: %s
- creating TLS storage configuration: %v
- cannot enable remote admin without a certificate cache; conf
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/bb3c34fa484846f4.
Report an issue: GitHub.