{"record":{"id":"4d432e29544772d5","repo":"caddyserver/caddy","slug":"field-s-does-not-exist-in-v","errorCode":null,"errorMessage":"field %s does not exist in %#v","messagePattern":"field (.+?) does not exist in %#v","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"context.go","lineNumber":194,"sourceCode":"//\n// This will look for a key/value pair like `\"handler\": \"...\"` in the json.RawMessage\n// in order to know the module name.\n//\n// To make use of the loaded module(s) (the return value), you will probably want\n// to type-assert each 'any' value(s) to the types that are useful to you\n// and store them on the same struct. Storing them on the same struct makes for\n// easy garbage collection when your host module is no longer needed.\n//\n// Loaded modules have already been provisioned and validated. Upon returning\n// 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) {","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/context.go#L176-L212","documentation":"Context.LoadModule uses reflection to fetch the named struct field and panics if it does not exist. This is an API-contract error: LoadModule is only meant to be called by a module on its own struct fields (those with a caddy struct tag), typically from within its own Provision method. A wrong fieldName or wrong struct pointer is a programming bug, so it panics rather than returning an error.","triggerScenarios":"Calling ctx.LoadModule(m, \"Wrap\") when the field is actually named WrappedRaw; passing a non-pointer or a pointer to a different struct; passing the host module's pointer plus a field that only exists on the embedded module type.","commonSituations":"Plugin development with renamed struct fields without updating the Provision body; typos in the fieldName string; calling LoadModule outside Provision where the receiver is not the module being loaded.","solutions":["Make the fieldName string exactly match the exported struct field that carries the caddy:\"namespace=...\" tag","Call ctx.LoadModule only from within that module's own Provision(ctx) on itself","Compile-time alternative: keep the string adjacent to the field definition and cover it with a unit test that provisions the module"],"exampleFix":"// before\ntype H struct {\n    UpstreamRaw json.RawMessage `caddy:\"namespace=http.reverse_proxy.upstreams\"`\n}\nfunc (h *H) Provision(ctx caddy.Context) error {\n    val, err := ctx.LoadModule(h, \"Upstream\") // wrong name -> panic\n}\n\n// after\nfunc (h *H) Provision(ctx caddy.Context) error {\n    val, err := ctx.LoadModule(h, \"UpstreamRaw\")\n    if err != nil { return err }\n    h.Upstream = val.(Upstream)\n    return nil\n}","handlingStrategy":"type-guard","validationCode":"if _, ok := reflect.TypeOf(m).Elem().FieldByName(fieldName); !ok {\n    return fmt.Errorf(\"field %s missing on %T — fix LoadModule call\", fieldName, m)\n}","typeGuard":"func hasCaddyField(ptr any, fieldName string) bool {\n    f, ok := reflect.TypeOf(ptr).Elem().FieldByName(fieldName)\n    return ok && f.Tag.Get(\"caddy\") != \"\"\n}\n\n// use before loading:\nif !hasCaddyField(&h, \"UpstreamRaw\") {\n    panic(\"programmer error: bad field name for LoadModule\")\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if strings.HasPrefix(fmt.Sprint(r), \"field \") && strings.Contains(fmt.Sprint(r), \"does not exist\") {\n            log.Fatalf(\"LoadModule called with wrong fieldName: %v\", r)\n        }\n        panic(r)\n    }\n}()\nval, err := ctx.LoadModule(&h, \"UpstreamRaw\")","preventionTips":["Only call ctx.LoadModule from the module's own Provision on its own tagged fields","Keep the fieldName string next to the field and cover with tests that run provisioning"],"tags":["caddy","module-system","reflection","panic","plugin"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}