{"record":{"id":"2533d826ddd7f0ce","repo":"caddyserver/caddy","slug":"expected-modulemap-because-inline-key-is-empty-bu","errorCode":null,"errorMessage":"expected ModuleMap because inline_key is empty; but we do not recognize this type: %s","messagePattern":"expected ModuleMap because inline_key is empty; but we do not recognize this type: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"context.go","lineNumber":305,"sourceCode":"}\n\n// emitEvent is a small convenience method so the caddy core can emit events, if the event app is configured.\nfunc (ctx Context) emitEvent(name string, data map[string]any) Event {\n\tif ctx.cfg == nil || ctx.cfg.eventEmitter == nil {\n\t\treturn Event{}\n\t}\n\treturn ctx.cfg.eventEmitter.Emit(ctx, name, data)\n}\n\n// loadModulesFromSomeMap loads modules from val, which must be a type of map[string]any.\n// Depending on inlineModuleKey, it will be interpreted as either a ModuleMap (key is the module\n// name) or as a regular map (key is not the module name, and module name is defined inline).\nfunc (ctx Context) loadModulesFromSomeMap(namespace, inlineModuleKey string, val reflect.Value) (map[string]any, error) {\n\t// if no inline_key is specified, then val must be a ModuleMap,\n\t// where the key is the module name\n\tif inlineModuleKey == \"\" {\n\t\tif !isModuleMapType(val.Type()) {\n\t\t\tpanic(fmt.Sprintf(\"expected ModuleMap because inline_key is empty; but we do not recognize this type: %s\", val.Type()))\n\t\t}\n\t\treturn ctx.loadModuleMap(namespace, val)\n\t}\n\n\t// otherwise, val is a map with modules, but the module name is\n\t// inline with each value (the key means something else)\n\treturn ctx.loadModulesFromRegularMap(namespace, inlineModuleKey, val)\n}\n\n// loadModulesFromRegularMap loads modules from val, where val is a map[string]json.RawMessage.\n// Map keys are NOT interpreted as module names, so module names are still expected to appear\n// inline with the objects.\nfunc (ctx Context) loadModulesFromRegularMap(namespace, inlineModuleKey string, val reflect.Value) (map[string]any, error) {\n\tmods := make(map[string]any)\n\titer := val.MapRange()\n\tfor iter.Next() {\n\t\tk := iter.Key()\n\t\tv := iter.Value()","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/context.go#L287-L323","documentation":"In loadModulesFromSomeMap, when the caddy tag has no inline_key, the field's map type must be a caddy.ModuleMap — its keys are the module names. If the field is a plain map[string]json.RawMessage (or other map type) and inline_key is empty, Caddy panics because map keys cannot be trusted to be module names. It is a type/tag mismatch in the module's source.","triggerScenarios":"Declaring a field as map[string]json.RawMessage with a tag lacking inline_key (e.g. `caddy:\"namespace=http.handlers\"`) and calling ctx.LoadModule.","commonSituations":"Custom modules using a generic map instead of caddy.ModuleMap; refactoring a ModuleMap field into a plain map and dropping inline_key; imitating upstream code with the wrong map type.","solutions":["Change the field type to caddy.ModuleMap so keys are interpreted as module names","Or keep map[string]json.RawMessage and add inline_key to the tag, embedding the module name inside each value object","Re-run provisioning after fixing to confirm the map values carry valid module names"],"exampleFix":"// before\ntype Handler struct {\n    Matchers map[string]json.RawMessage `json:\"match,omitempty\" caddy:\"namespace=http.matchers\"`\n}\n// after\nimport \"github.com/caddyserver/caddy/v2\"\ntype Handler struct {\n    Matchers caddy.ModuleMap `json:\"match,omitempty\" caddy:\"namespace=http.matchers\"`\n}","handlingStrategy":"type-guard","validationCode":"import \"reflect\"\n\nfunc isModuleMap(t reflect.Type) bool {\n    return t == reflect.TypeOf(caddy.ModuleMap{})\n}","typeGuard":"// use the concrete type directly so a wrong declaration cannot compile-land silently\ntype MyHandler struct {\n    Matchers caddy.ModuleMap `json:\"match,omitempty\" caddy:\"namespace=http.matchers\"`\n}","tryCatchPattern":"defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"loadModulesFromSomeMap: %v\", r) } }()","preventionTips":["Without inline_key, declare the field as caddy.ModuleMap","With plain map[string]json.RawMessage, always add inline_key","Test both JSON shapes your module accepts"],"tags":["caddy","go","module-system","modulemap","panic"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}