caddyserver/caddy · error · ErrNotConfigured
app module %s: %w
Error message
app module %s: %w
What it means
AppIfConfigured is like App but errors with ErrNotConfigured when the app is absent. This branch fires when ctx.cfg itself is nil — i.e. the Context has no configuration at all — returning 'app module %s: %w' wrapping ErrNotConfigured. A nil cfg means the context cannot possibly have the app, so it is reported as not configured.
Source
Thrown at context.go:532
modVal, err := ctx.LoadModuleByID(name, appRaw)
if err != nil {
return nil, fmt.Errorf("loading %s app module: %v", name, err)
}
if appRaw != nil {
ctx.cfg.AppsRaw[name] = nil // allow GC to deallocate
}
return modVal, nil
}
// AppIfConfigured is like App, but it returns an error if the
// app has not been configured. This is useful when the app is
// required and its absence is a configuration error; or when
// the app is optional and you don't want to instantiate a
// new one that hasn't been explicitly configured. If the app
// is not in the configuration, the error wraps ErrNotConfigured.
func (ctx Context) AppIfConfigured(name string) (any, error) {
if ctx.cfg == nil {
return nil, fmt.Errorf("app module %s: %w", name, ErrNotConfigured)
}
// if the app failed to load before, return the cached error
if err, ok := ctx.cfg.failedApps[name]; ok {
return nil, fmt.Errorf("loading %s app module: %v", name, err)
}
if app, ok := ctx.cfg.apps[name]; ok {
return app, nil
}
appRaw := ctx.cfg.AppsRaw[name]
if appRaw == nil {
return nil, fmt.Errorf("app module %s: %w", name, ErrNotConfigured)
}
return ctx.App(name)
}
// ErrNotConfigured indicates a module is not configured.
var ErrNotConfigured = fmt.Errorf("module not configured")
View on GitHub (pinned to 50e54ee279)
Solutions
- Obtain the Context from a loaded config: cfg := &caddy.Config{}; ctx := cfg.NewContext(caddy.Context{}) — never use a zero-value Context for app access
- Check errors.Is(err, caddy.ErrNotConfigured) to treat absence as optional rather than fatal
- In tests, build a minimal Config with the needed AppsRaw/apps entries
Example fix
// before
ctx := caddy.Context{} // no cfg
app, err := ctx.AppIfConfigured("tls")
// after
cfg := &caddy.Config{}
ctx := cfg.NewContext(caddy.Context{})
app, err := ctx.AppIfConfigured("tls") Defensive patterns
Strategy: validation
Validate before calling
// Never call AppIfConfigured on a context without a config
cfg := &caddy.Config{ AppsRaw: caddy.ModuleMap{ "tls": json.RawMessage(`{}`) } }
ctx := cfg.NewContext(caddy.Context{})
if _, err := ctx.AppIfConfigured("tls"); err != nil { /* handle */ } Type guard
func contextHasConfig(ctx caddy.Context) bool { return ctx != caddy.Context{} /* prefer constructing contexts only from real configs */ } Try / catch
if _, err := ctx.AppIfConfigured(name); err != nil {
if errors.Is(err, caddy.ErrNotConfigured) { /* absent: use defaults */ } else { return err }
} Prevention
- Always create Context via cfg.NewContext, never caddy.Context{}
- Treat ErrNotConfigured as an expected, handled branch
- In tests, build a minimal Config with the apps you need
When it happens
Trigger: Calling ctx.AppIfConfigured(name) on a Context constructed without a config (e.g. zero-value Context or one created for tests/tooling), hitting the ctx.cfg == nil guard and wrapping ErrNotConfigured with the app name.
Common situations: Unit tests or embedding code creating caddy.Context{} directly instead of via cfg.NewContext; calling app-dependent helpers before a config is loaded.
Related errors
- module not configured
- %v; additionally, aborting app %s: %v
- %s app module: start: %v
- loading %s app module: %v
- getting tls app: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/139ceb53b0a35991.
Report an issue: GitHub.