{"record":{"id":"24eb36fae3dea310","repo":"caddyserver/caddy","slug":"missing-namespace-key-in-struct-tag-on-field-s","errorCode":null,"errorMessage":"missing 'namespace' key in struct tag on field %s","messagePattern":"missing 'namespace' key in struct tag on field (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"context.go","lineNumber":204,"sourceCode":"// successfully, this method clears the json.RawMessage(s) in the field since\n// the raw JSON is no longer needed, and this allows the GC to free up memory.\nfunc (ctx Context) LoadModule(structPointer any, fieldName string) (any, error) {\n\tval := reflect.ValueOf(structPointer).Elem().FieldByName(fieldName)\n\ttyp := val.Type()\n\n\tfield, ok := reflect.TypeOf(structPointer).Elem().FieldByName(fieldName)\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"field %s does not exist in %#v\", fieldName, structPointer))\n\t}\n\n\topts, err := ParseStructTag(field.Tag.Get(\"caddy\"))\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"malformed tag on field %s: %v\", fieldName, err))\n\t}\n\n\tmoduleNamespace, ok := opts[\"namespace\"]\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"missing 'namespace' key in struct tag on field %s\", fieldName))\n\t}\n\tinlineModuleKey := opts[\"inline_key\"]\n\n\tvar result any\n\n\tswitch val.Kind() {\n\tcase reflect.Slice:\n\t\tif isJSONRawMessage(typ) {\n\t\t\t// val is `json.RawMessage` ([]uint8 under the hood)\n\n\t\t\tif inlineModuleKey == \"\" {\n\t\t\t\tpanic(\"unable to determine module name without inline_key when type is not a ModuleMap\")\n\t\t\t}\n\t\t\tval, err := ctx.loadModuleInline(inlineModuleKey, moduleNamespace, val.Interface().(json.RawMessage))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tresult = val","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/context.go#L186-L222","documentation":"Context.LoadModule requires the field's `caddy:\"...\"` struct tag to contain a `namespace` key so it knows which module namespace to instantiate from (e.g. http.handlers). The tag parsed successfully but had no namespace entry, so Caddy cannot resolve candidate modules. This is a source-code defect in the module definition and panics at provision time.","triggerScenarios":"Calling ctx.LoadModule on a field whose tag only has inline_key, e.g. `caddy:\"inline_key=handler\"`, or is empty `caddy:\"\"`.","commonSituations":"Authoring a custom Caddy module and forgetting the namespace in the tag; renaming the tag key (name_space, ns) while coding; tags for map fields where the author assumed the key is implied.","solutions":["Add the namespace to the struct tag: `caddy:\"namespace=<your.namespace>\"` using the same namespace as the registered module IDs","Check the module ID you registered via caddy.RegisterModule and use everything before the last dot as the namespace","Compare against a working upstream module's tag (e.g. caddyhttp handler fields)"],"exampleFix":"// before\ntype Middleware struct {\n    Matcher json.RawMessage `json:\"match,omitempty\" caddy:\"inline_key=matcher\"`\n}\n// after\ntype Middleware struct {\n    Matcher json.RawMessage `json:\"match,omitempty\" caddy:\"namespace=http.matchers.inline_key=matcher\"` // ensure correct: namespace=http.matchers plus inline_key\n}","handlingStrategy":"validation","validationCode":"import \"reflect\"\n\nfunc requireNamespaceTag(ptr any, fieldName string) error {\n    f, _ := reflect.TypeOf(ptr).Elem().FieldByName(fieldName)\n    opts, err := caddy.ParseStructTag(f.Tag.Get(\"caddy\"))\n    if err != nil {\n        return err\n    }\n    if _, ok := opts[\"namespace\"]; !ok {\n        return fmt.Errorf(\"field %s: caddy tag must declare namespace\", fieldName)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"LoadModule: %v\", r) } }()","preventionTips":["Namespace must equal the registered module ID minus the last segment","Test provisioning of new modules in CI","Never ship struct tags written from memory alone; copy a known-good one"],"tags":["caddy","go","module-system","struct-tag","panic"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}