{"record":{"id":"a89bbf44a605911c","repo":"caddyserver/caddy","slug":"loading-s-app-module-v","errorCode":null,"errorMessage":"loading %s app module: %v","messagePattern":"loading (.+?) app module: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"context.go","lineNumber":508,"sourceCode":"}\n\n// App returns the configured app named name. If that app has\n// not yet been loaded and provisioned, it will be immediately\n// loaded and provisioned. If no app with that name is\n// configured, a new empty one will be instantiated instead.\n// (The app module must still be registered.) This must not be\n// called during the Provision/Validate phase to reference a\n// module's own host app (since the parent app module is still\n// in the process of being provisioned, it is not yet ready).\n//\n// We return any type instead of the App type because it is NOT\n// intended for the caller of this method to be the one to start\n// or stop App modules. The caller is expected to assert to the\n// concrete type.\nfunc (ctx Context) App(name string) (any, error) {\n\t// if the app failed to load before, return the cached error\n\tif err, ok := ctx.cfg.failedApps[name]; ok {\n\t\treturn nil, fmt.Errorf(\"loading %s app module: %v\", name, err)\n\t}\n\tif app, ok := ctx.cfg.apps[name]; ok {\n\t\treturn app, nil\n\t}\n\tappRaw := ctx.cfg.AppsRaw[name]\n\tmodVal, err := ctx.LoadModuleByID(name, appRaw)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"loading %s app module: %v\", name, err)\n\t}\n\tif appRaw != nil {\n\t\tctx.cfg.AppsRaw[name] = nil // allow GC to deallocate\n\t}\n\treturn modVal, nil\n}\n\n// AppIfConfigured is like App, but it returns an error if the\n// app has not been configured. This is useful when the app is\n// required and its absence is a configuration error; or when","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/context.go#L490-L526","documentation":"Context.App(name) loads and provisions an app module on demand. If that app previously failed to load during this config load, the failure is cached in cfg.failedApps and replayed as 'loading %s app module: %v' for every subsequent caller — so modules depending on a broken app get a consistent error instead of retrying. The %v is the original LoadModuleByID failure.","triggerScenarios":"Something calls ctx.App(\"tls\") (or another app) after that app's provisioning already failed; the cached error branch returns fmt.Errorf(\"loading %s app module: %v\", name, err) immediately.","commonSituations":"The http app failing mid-provision and a submodule then requesting the tls/pki app; cascading errors during `caddy run`/reload where the first root-cause error for the app appears earlier in logs; inter-app dependencies (tls referencing apps) surfacing repeated wrapped errors.","solutions":["Scroll up in the logs: the first error for this app (not this wrapped replay) is the root cause — fix that (usually a provision/validate/decode failure inside the app's own config)","Validate the whole config with `caddy validate` to get a single clean error chain","Correct the app-level configuration (apps section of the JSON) per the underlying error","In plugin code, avoid calling ctx.App for your own host app during Provision (documented restriction) — use ctx.App for other apps only"],"exampleFix":"// before (plugin Provision)\nfunc (h *H) Provision(ctx caddy.Context) error {\n    app, err := ctx.App(\"http\") // own host app — wrong during provisioning\n// after\n// design the module to receive needed data via config fields; only call ctx.App for OTHER apps","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := ctx.App(\"tls\"); err != nil {\n    // cached replay: the first failure for this app is elsewhere in logs — fix that, do not retry here\n    return fmt.Errorf(\"tls app unavailable: %w\", err)\n}","preventionTips":["Fix the first logged error for a failing app, not the wrapped replays","Use `caddy validate` to get a single consolidated error chain","Do not call ctx.App for a module's own host app during Provision"],"tags":["caddy","apps","provisioning","error-caching","dependencies"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}