{"record":{"id":"a7dbb859e2379e52","repo":"caddyserver/caddy","slug":"unable-to-determine-module-name-without-inline-key-a7dbb8","errorCode":null,"errorMessage":"unable to determine module name without inline_key because type is not a ModuleMap","messagePattern":"unable to determine module name without inline_key because type is not a ModuleMap","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"context.go","lineNumber":227,"sourceCode":"\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\n\t\t} else if isJSONRawMessage(typ.Elem()) {\n\t\t\t// val is `[]json.RawMessage`\n\n\t\t\tif inlineModuleKey == \"\" {\n\t\t\t\tpanic(\"unable to determine module name without inline_key because type is not a ModuleMap\")\n\t\t\t}\n\t\t\tvar all []any\n\t\t\tfor i := 0; i < val.Len(); i++ {\n\t\t\t\tval, err := ctx.loadModuleInline(inlineModuleKey, moduleNamespace, val.Index(i).Interface().(json.RawMessage))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"position %d: %v\", i, err)\n\t\t\t\t}\n\t\t\t\tall = append(all, val)\n\t\t\t}\n\t\t\tresult = all\n\t\t} else if typ.Elem().Kind() == reflect.Slice && isJSONRawMessage(typ.Elem().Elem()) {\n\t\t\t// val is `[][]json.RawMessage`\n\n\t\t\tif inlineModuleKey == \"\" {\n\t\t\t\tpanic(\"unable to determine module name without inline_key because type is not a ModuleMap\")\n\t\t\t}\n\t\t\tvar all [][]any\n\t\t\tfor i := 0; i < val.Len(); i++ {","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/context.go#L209-L245","documentation":"Same contract as for a single json.RawMessage, but the field is a []json.RawMessage (slice of raw module configs). Each element needs an inline module name, so the tag must declare inline_key; without it LoadModule panics because it cannot derive module names. This is a compile-time-visible design mistake in the module struct.","triggerScenarios":"Declaring a field as []json.RawMessage whose tag lacks inline_key, e.g. `caddy:\"namespace=http.matchers\"`, then calling ctx.LoadModule.","commonSituations":"Custom modules holding a list of matcher/handler blobs; converting a ModuleMap list to a raw-message slice for ordering guarantees while keeping the old tag.","solutions":["Add inline_key to the struct tag so each JSON element carries its module name","Or switch the field type to caddy.ModuleMap / caddy.ModuleMap-based types when map keys should name modules","Validate that every element of the JSON array contains the inline_key property"],"exampleFix":"// before\ntype Route struct {\n    Matchers []json.RawMessage `json:\"match,omitempty\" caddy:\"namespace=http.matchers\"`\n}\n// after\ntype Route struct {\n    Matchers []json.RawMessage `json:\"match,omitempty\" caddy:\"namespace=http.matchers inline_key=matcher\"`\n}","handlingStrategy":"validation","validationCode":"func requireSliceInlineKey(ptr any, fieldName string) error {\n    f, _ := reflect.TypeOf(ptr).Elem().FieldByName(fieldName)\n    if f.Type.Kind() == reflect.Slice && f.Type.Elem() == reflect.TypeOf(json.RawMessage{}) {\n        opts, _ := caddy.ParseStructTag(f.Tag.Get(\"caddy\"))\n        if opts[\"inline_key\"] == \"\" {\n            return fmt.Errorf(\"%s is []json.RawMessage; needs inline_key\", fieldName)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"LoadModule: %v\", r) } }()","preventionTips":["Slices of raw JSON require inline_key","Validate JSON elements contain the inline key before provisioning","Mirror caddyhttp's matcher patterns for ordered lists"],"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"}