{"record":{"id":"5f45d05a89d97305","repo":"caddyserver/caddy","slug":"module-id-s-is-reserved","errorCode":null,"errorMessage":"module ID '%s' is reserved","messagePattern":"module ID '(.+?)' is reserved","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"modules.go","lineNumber":145,"sourceCode":"// json.RawMessage.\ntype ModuleMap map[string]json.RawMessage\n\n// RegisterModule registers a module by receiving a\n// plain/empty value of the module. For registration to\n// be properly recorded, this should be called in the\n// init phase of runtime. Typically, the module package\n// will do this as a side-effect of being imported.\n// This function panics if the module's info is\n// incomplete or invalid, or if the module is already\n// registered.\nfunc RegisterModule(instance Module) {\n\tmod := instance.CaddyModule()\n\n\tif mod.ID == \"\" {\n\t\tpanic(\"module ID missing\")\n\t}\n\tif mod.ID == \"caddy\" || mod.ID == \"admin\" {\n\t\tpanic(fmt.Sprintf(\"module ID '%s' is reserved\", mod.ID))\n\t}\n\tif mod.New == nil {\n\t\tpanic(\"missing ModuleInfo.New\")\n\t}\n\tif val := mod.New(); val == nil {\n\t\tpanic(\"ModuleInfo.New must return a non-nil module instance\")\n\t}\n\n\tmodulesMu.Lock()\n\tdefer modulesMu.Unlock()\n\n\tif _, ok := modules[string(mod.ID)]; ok {\n\t\tpanic(fmt.Sprintf(\"module already registered: %s\", mod.ID))\n\t}\n\tmodules[string(mod.ID)] = mod\n}\n\n// GetModule returns module information from its ID (full name).","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules.go#L127-L163","documentation":"The module IDs \"caddy\" and \"admin\" are reserved by the core and cannot be claimed by plugins. RegisterModule panics if a module uses one of them, because these top-level identities back core config schemas and colliding would break the config system.","triggerScenarios":"Setting ID: \"caddy\" or ID: \"admin\" in a module's CaddyModule() and importing the package so init() runs RegisterModule.","commonSituations":"Writing a top-level app-like module and guessing a short ID; porting an app whose name happens to be 'admin'; misunderstanding that only core may own these roots.","solutions":["Pick a namespaced ID such as \"myapp.admin\" or \"http.apps.myadmin\"","Prefix custom app IDs with your organization/plugin name to avoid all core collisions","Check existing module IDs with caddy list-modules before naming"],"exampleFix":"// before\nreturn caddy.ModuleInfo{ID: \"admin\", New: ...}\n// after\nreturn caddy.ModuleInfo{ID: \"myplugin.admin\", New: ...}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use bare \"caddy\" or \"admin\" as module IDs","Namespace app IDs with your org/plugin name","Check caddy list-modules output for collisions before release"],"tags":["caddy","go","module-system","reserved-name","panic"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}