{"record":{"id":"5e1d48d8ca1f2c10","repo":"caddyserver/caddy","slug":"unknown-module-s","errorCode":null,"errorMessage":"unknown module: %s","messagePattern":"unknown module: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"context.go","lineNumber":369,"sourceCode":"\treturn all, nil\n}\n\n// LoadModuleByID decodes rawMsg into a new instance of mod and\n// returns the value. If mod.New is nil, an error is returned.\n// If the module implements Validator or Provisioner interfaces,\n// those methods are invoked to ensure the module is fully\n// configured and valid before being used.\n//\n// This is a lower-level method and will usually not be called\n// directly by most modules. However, this method is useful when\n// dynamically loading/unloading modules in their own context,\n// like from embedded scripts, etc.\nfunc (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error) {\n\tmodulesMu.RLock()\n\tmodInfo, ok := modules[id]\n\tmodulesMu.RUnlock()\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unknown module: %s\", id)\n\t}\n\n\tif modInfo.New == nil {\n\t\treturn nil, fmt.Errorf(\"module '%s' has no constructor\", modInfo.ID)\n\t}\n\n\tval := modInfo.New()\n\n\t// value must be a pointer for unmarshaling into concrete type, even if\n\t// the module's concrete type is a slice or map; New() *should* return\n\t// a pointer, otherwise unmarshaling errors or panics will occur\n\tif rv := reflect.ValueOf(val); rv.Kind() != reflect.Pointer {\n\t\tlog.Printf(\"[WARNING] ModuleInfo.New() for module '%s' did not return a pointer,\"+\n\t\t\t\" so we are using reflection to make a pointer instead; please fix this by\"+\n\t\t\t\" using new(Type) or &Type notation in your module's New() function.\", id)\n\t\tval = reflect.New(rv.Type()).Elem().Addr().Interface().(Module)\n\t}\n","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/context.go#L351-L387","documentation":"LoadModuleByID looks the requested module ID up in the global registry populated by caddy.RegisterModule (usually via plugin init() functions and modules/standard/imports.go). If the ID is absent it returns 'unknown module: %s'. Common root causes: the plugin is not compiled into this binary, the ID is misspelled, or the namespace/name doesn't match what was registered.","triggerScenarios":"Calling ctx.LoadModuleByID(\"http.handlers.foo\", raw) where no module with that exact ID was registered — plugin not imported, custom build missing it, or the ID string constructed with the wrong namespace/scope (e.g. concatenating an empty moduleScope producing '.foo').","commonSituations":"Deploying a JSON config produced elsewhere to a stock Caddy binary that lacks third-party plugins; upgrading Caddy where a plugin's module ID changed; typos in module IDs in hand-written JSON; empty namespace producing malformed IDs when loading inline modules.","solutions":["Run `caddy list-modules` and confirm the exact module ID exists in this build; compare character-for-character with the error","If it is a plugin module, build a custom binary: `xcaddy build --with github.com/user/plugin`","Correct the namespace in the config or in the code building the ID (e.g. the caddy:\"module=...\" tag or the moduleScope passed to loadModuleInline)","Pin matching versions: ensure the plugin version supports your Caddy version's module ID scheme"],"exampleFix":"// before\nxcaddy build # forgot --with, then config references http.handlers.my_plugin\n// after\nxcaddy build --with github.com/user/caddy-myplugin","handlingStrategy":"validation","validationCode":"// Guard LoadModuleByID calls with a registry check\nif !moduleRegistered(\"http.handlers.foo\") {\n    return fmt.Errorf(\"cannot proceed: build custom caddy with the foo plugin\")\n}\nval, err := ctx.LoadModuleByID(\"http.handlers.foo\", raw)","typeGuard":"func moduleRegistered(id string) bool {\n    for _, m := range caddy.Modules() {\n        if m == id { return true }\n    }\n    return false\n}","tryCatchPattern":"val, err := ctx.LoadModuleByID(id, raw)\nif err != nil {\n    if strings.Contains(err.Error(), \"unknown module\") {\n        // registry problem: fix build or ID, do not retry\n    }\n    return err\n}","preventionTips":["Run `caddy list-modules` on the target binary before writing configs","Include every needed plugin in `xcaddy build --with ...`","Prefix module IDs with the correct namespace (e.g. http.handlers., dns., tls.)"],"tags":["caddy","module-system","registration","plugins"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}