{"record":{"id":"2e608e6af5e9a308","repo":"caddyserver/caddy","slug":"module-not-configured","errorCode":null,"errorMessage":"module not configured","messagePattern":"module not configured","errorType":"error_code","errorClass":"ErrNotConfigured","httpStatus":null,"severity":"error","filePath":"context.go","lineNumber":549,"sourceCode":"\tif ctx.cfg == nil {\n\t\treturn nil, fmt.Errorf(\"app module %s: %w\", name, ErrNotConfigured)\n\t}\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\tif appRaw == nil {\n\t\treturn nil, fmt.Errorf(\"app module %s: %w\", name, ErrNotConfigured)\n\t}\n\treturn ctx.App(name)\n}\n\n// ErrNotConfigured indicates a module is not configured.\nvar ErrNotConfigured = fmt.Errorf(\"module not configured\")\n\n// Storage returns the configured Caddy storage implementation.\nfunc (ctx Context) Storage() certmagic.Storage {\n\treturn ctx.cfg.storage\n}\n\n// Logger returns a logger that is intended for use by the most\n// recent module associated with the context. Callers should not\n// pass in any arguments unless they want to associate with a\n// different module; it panics if more than 1 value is passed in.\n//\n// Originally, this method's signature was `Logger(mod Module)`,\n// requiring that an instance of a Caddy module be passed in.\n// However, that is no longer necessary, as the closest module\n// most recently associated with the context will be automatically\n// assumed. To prevent a sudden breaking change, this method's\n// signature has been changed to be variadic, but we may remove\n// the parameter altogether in the future. Callers should not","sourceCodeStart":531,"sourceCodeEnd":567,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/context.go#L531-L567","documentation":"ErrNotConfigured is the exported sentinel error (\"module not configured\") that AppIfConfigured wraps when an app is absent from the configuration. Callers are expected to test for it with errors.Is to distinguish 'not configured' from genuine load failures. Seeing this bare text means a wrapped error chain bottomed out at this sentinel.","triggerScenarios":"Any AppIfConfigured call for an app missing from cfg (nil cfg, or no entry in apps/AppsRaw) unwraps to this sentinel; code that prints err.Error() on the returned error shows 'app module <name>: module not configured'.","commonSituations":"Plugin code needing to know whether e.g. the tls or pki app was user-configured; Caddyfile-derived configs where omitting a global option means the app is absent; version migrations where an app moved from implicit to explicit configuration.","solutions":["Use errors.Is(err, caddy.ErrNotConfigured) instead of string matching to detect absence","Supply the app config if the app is required for your module to function","Design submodules to operate with sensible defaults when the host app is not configured"],"exampleFix":"// before\nif strings.Contains(err.Error(), \"not configured\") { ... }\n// after\nif errors.Is(err, caddy.ErrNotConfigured) { ... }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isNotConfigured(err error) bool { return errors.Is(err, caddy.ErrNotConfigured) }","tryCatchPattern":"if _, err := ctx.AppIfConfigured(name); err != nil {\n    switch {\n    case errors.Is(err, caddy.ErrNotConfigured):\n        // not configured — expected for optional apps\n    default:\n        return err // real load failure\n    }\n}","preventionTips":["Never string-match error text; always errors.Is against caddy.ErrNotConfigured","Document which apps your module treats as optional","Handle the sentinel at the boundary and fall back to documented defaults"],"tags":["caddy","apps","sentinel-error","not-configured"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}