caddyserver/caddy · critical
missing ModuleInfo.New
Error message
missing ModuleInfo.New
What it means
ModuleInfo.New is the factory Caddy calls to instantiate a module during config unmarshal and provisioning. If New is nil, Caddy could never create instances, so RegisterModule panics at init time. This catches an incomplete CaddyModule() implementation before it can cause nil-pointer chaos later.
Source
Thrown at modules.go:148
// RegisterModule registers a module by receiving a
// plain/empty value of the module. For registration to
// be properly recorded, this should be called in the
// init phase of runtime. Typically, the module package
// will do this as a side-effect of being imported.
// This function panics if the module's info is
// incomplete or invalid, or if the module is already
// registered.
func RegisterModule(instance Module) {
mod := instance.CaddyModule()
if mod.ID == "" {
panic("module ID missing")
}
if mod.ID == "caddy" || mod.ID == "admin" {
panic(fmt.Sprintf("module ID '%s' is reserved", mod.ID))
}
if mod.New == nil {
panic("missing ModuleInfo.New")
}
if val := mod.New(); val == nil {
panic("ModuleInfo.New must return a non-nil module instance")
}
modulesMu.Lock()
defer modulesMu.Unlock()
if _, ok := modules[string(mod.ID)]; ok {
panic(fmt.Sprintf("module already registered: %s", mod.ID))
}
modules[string(mod.ID)] = mod
}
// GetModule returns module information from its ID (full name).
func GetModule(name string) (ModuleInfo, error) {
modulesMu.RLock()
defer modulesMu.RUnlock()View on GitHub (pinned to 50e54ee279)
Solutions
- Add New: func() caddy.Module { return new(YourType) } to the ModuleInfo
- Ensure New returns a pointer or value of your module type each call (fresh instance)
- Keep the compile-time guard var _ caddy.Module = (*YourType)(nil) so signature drift is caught
Example fix
// before
return caddy.ModuleInfo{ID: "http.handlers.x"}
// after
return caddy.ModuleInfo{
ID: "http.handlers.x",
New: func() caddy.Module { return new(XHandler) },
} Defensive patterns
Strategy: validation
Prevention
- ModuleInfo must contain both ID and New
- Keep the interface guard var _ caddy.Module = (*T)(nil)
- Test that a config referencing the module round-trips
When it happens
Trigger: Returning a ModuleInfo with ID set but no New function: caddy.ModuleInfo{ID: "http.handlers.x"}.
Common situations: Hand-writing a module skeleton and filling in ID first; deleting the New closure during refactoring; interface-guard copies that drop fields.
Related errors
- module ID missing
- ModuleInfo.New must return a non-nil module instance
- malformed tag on field %s: %v
- missing 'namespace' key in struct tag on field %s
- unable to determine module name without inline_key when type
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/9bfe3414f6318ad3.
Report an issue: GitHub.