{"record":{"id":"84add9c18c2ee85c","repo":"caddyserver/caddy","slug":"loading-storage-module-v-84add9","errorCode":null,"errorMessage":"loading storage module: %v","messagePattern":"loading storage module: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddypki/ca.go","lineNumber":114,"sourceCode":"}\n\n// Provision sets up the CA.\nfunc (ca *CA) Provision(ctx caddy.Context, id string, log *zap.Logger) error {\n\tca.mu = new(sync.RWMutex)\n\tca.log = log.Named(\"ca.\" + id)\n\tca.ctx = ctx\n\n\tif id == \"\" {\n\t\treturn fmt.Errorf(\"CA ID is required (use 'local' for the default CA)\")\n\t}\n\tca.mu.Lock()\n\tca.ID = id\n\tca.mu.Unlock()\n\n\tif ca.StorageRaw != nil {\n\t\tval, err := ctx.LoadModule(ca, \"StorageRaw\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"loading storage module: %v\", err)\n\t\t}\n\t\tcmStorage, err := val.(caddy.StorageConverter).CertMagicStorage()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"creating storage configuration: %v\", err)\n\t\t}\n\t\tca.storage = cmStorage\n\t}\n\tif ca.storage == nil {\n\t\tca.storage = ctx.Storage()\n\t}\n\n\tif ca.Name == \"\" {\n\t\tca.Name = defaultCAName\n\t}\n\tif ca.RootCommonName == \"\" {\n\t\tca.RootCommonName = defaultRootCommonName\n\t}\n\tif ca.IntermediateCommonName == \"\" {","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddypki/ca.go#L96-L132","documentation":"Returned by CA.Provision when ctx.LoadModule(ca, \"StorageRaw\") fails to load the CA's custom storage module from its raw JSON. LoadModule resolves the module name in the storage namespace and instantiates it; failure means an unknown module name, a module not compiled into the binary, or malformed module JSON. The %v wraps caddy's module-loading error, which names the offending module.","triggerScenarios":"Configuring a CA with \"storage\": {\"module\": \"redis\", ...} when the caddy.storage.redis plugin is not built into the custom Caddy binary; a typo in the module key; JSON for the storage module that fails its own unmarshaling. LoadModule returns the error and it is re-wrapped here.","commonSituations":"Switching from a plugin build (xcaddy) to the stock caddy binary and keeping custom storage config; plugin removed during a build-script cleanup; storage module renamed between plugin versions; env-specific configs where only some builds include the plugin.","solutions":["Check the wrapped error — it says which module failed to load","Build Caddy with the plugin: xcaddy build --with github.com/.../caddy-storage-redis, or use a build that includes it","Fix the module name under storage.module to match the plugin's registered caddy.ModuleInfo ID","Or drop the per-CA storage block to fall back to the global/default storage"],"exampleFix":"# before (stock binary)\ncaddy run --config Caddyfile   # storage.module: redis → error\n\n# after\nxcaddy build --with github.com/graywindy/caddy-storage-redis\n./caddy run --config Caddyfile","handlingStrategy":"validation","validationCode":"// Verify the storage plugin is compiled in before loading config:\ncmd := exec.Command(caddyBin, \"list-modules\")\nout, _ := cmd.Output()\nif !bytes.Contains(out, []byte(\"caddy.storage.\"+moduleName)) {\n    return fmt.Errorf(\"storage module %q not in build; rebuild with xcaddy --with\", moduleName)\n}","typeGuard":"// After loading, assert the module implements StorageConverter:\nif _, ok := loaded.(caddy.StorageConverter); !ok {\n    return errors.New(\"module is not a storage converter\")\n}","tryCatchPattern":"// Catch the wrap and point at the build, not the config:\nif err := ca.Provision(ctx, id, log); err != nil {\n    if strings.Contains(err.Error(), \"loading storage module\") {\n        return fmt.Errorf(\"storage plugin missing from build: %v\", err)\n    }\n}","preventionTips":["Build with xcaddy including every storage plugin referenced by config","Run `caddy list-modules` as a deploy-time smoke test","Keep the plugin set in sync with the config repo"],"tags":["pki","storage","modules","plugin","config"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}