caddyserver/caddy · error
more than 1 module passed in
Error message
more than 1 module passed in
What it means
Context.Logger is variadic only for backward compatibility; it accepts at most zero or one Module argument. Passing two or more modules is a caller bug (the extra arguments came from the deprecated Logger(module) form) and triggers an immediate panic.
Source
Thrown at context.go:575
// recent module associated with the context. Callers should not
// pass in any arguments unless they want to associate with a
// different module; it panics if more than 1 value is passed in.
//
// Originally, this method's signature was `Logger(mod Module)`,
// requiring that an instance of a Caddy module be passed in.
// However, that is no longer necessary, as the closest module
// most recently associated with the context will be automatically
// assumed. To prevent a sudden breaking change, this method's
// signature has been changed to be variadic, but we may remove
// the parameter altogether in the future. Callers should not
// pass in any argument. If there is valid need to specify a
// different module, please open an issue to discuss.
//
// PARTIALLY DEPRECATED: The Logger(module) form is deprecated and
// may be removed in the future. Do not pass in any arguments.
func (ctx Context) Logger(module ...Module) *zap.Logger {
if len(module) > 1 {
panic("more than 1 module passed in")
}
if ctx.cfg == nil {
// often the case in tests; just use a dev logger
l, err := zap.NewDevelopment()
if err != nil {
panic("config missing, unable to create dev logger: " + err.Error())
}
return l
}
mod := ctx.Module()
if len(module) > 0 {
mod = module[0]
}
if mod == nil {
return Log()
}
return ctx.cfg.Logging.Logger(mod)
}View on GitHub (pinned to 50e54ee279)
Solutions
- Pass no argument: ctx.Logger() — the context's own module is used automatically
- If you must override, pass exactly one module: ctx.Logger(mod)
- Never splat a slice into Logger; select a single element first
Example fix
// before logger := ctx.Logger(modA, modB) // after logger := ctx.Logger()
Defensive patterns
Strategy: validation
Validate before calling
if len(modules) > 1 {
return nil, fmt.Errorf("Logger accepts at most one module, got %d", len(modules))
}
logger := ctx.Logger(modules...) Prevention
- Call ctx.Logger() with no arguments — the deprecated form needs none
- Never splat slices into variadic Logger
- Staticcheck can flag suspicious splats of deprecated params
When it happens
Trigger: Calling ctx.Logger(modA, modB) — any call with len(module) > 1.
Common situations: Migrating old code that called Logger(mod) and accidentally splatting a slice: ctx.Logger(mods...); grep-and-replace introducing multiple arguments; IDE autocompletion adding extra params.
Related errors
- config missing, unable to create dev logger: %v
- malformed tag on field %s: %v
- missing 'namespace' key in struct tag on field %s
- unable to determine module name without inline_key when type
- unable to determine module name without inline_key because t
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/c3978f14a6e9f136.
Report an issue: GitHub.