caddyserver/caddy · error
loading log writer module: %v
Error message
loading log writer module: %v
What it means
BaseLog.provisionCommon loads the writer module from the log's WriterRaw JSON. If ctx.LoadModule fails — unknown module ID in the writer object, malformed JSON shape for the module, or the module not compiled in — this error is returned. It is the common root cause wrapped by the 'setting up ... log' errors above.
Source
Thrown at logging.go:346
WithCallerSkip int `json:"with_caller_skip,omitempty"`
// If not empty, the log entry will include a stack trace
// for all logs at the given level or higher. See `level`
// for possible values. Default off.
WithStacktrace string `json:"with_stacktrace,omitempty"`
writerOpener WriterOpener
writer io.WriteCloser
encoder zapcore.Encoder
levelEnabler zapcore.LevelEnabler
core zapcore.Core
}
func (cl *BaseLog) provisionCommon(ctx Context, logging *Logging) error {
if cl.WriterRaw != nil {
mod, err := ctx.LoadModule(cl, "WriterRaw")
if err != nil {
return fmt.Errorf("loading log writer module: %v", err)
}
cl.writerOpener = mod.(WriterOpener)
}
if cl.writerOpener == nil {
cl.writerOpener = StderrWriter{}
}
var err error
cl.writer, _, err = logging.openWriter(cl.writerOpener)
if err != nil {
return fmt.Errorf("opening log writer using %#v: %v", cl.writerOpener, err)
}
// set up the log level
cl.levelEnabler, err = parseLevel(cl.Level)
if err != nil {
return err
}
View on GitHub (pinned to 50e54ee279)
Solutions
- Use exact writer names: 'stderr', 'stdout', 'file', 'net'.
- Match field names to the writer's schema (filename, roll_size_mb, etc. for file).
- For custom/xcaddy builds, verify the writer module is registered in the binary you run.
- Validate with 'caddy validate --config <file>' after edits.
Example fix
// before
"writer": { "output": "Stdout" }
// after
"writer": { "output": "stdout" } Defensive patterns
Strategy: type-guard
Validate before calling
var knownWriters = map[string]bool{"stderr": true, "stdout": true, "file": true, "net": true, "discard": true}
func writerKnown(w map[string]any) bool {
out, _ := w["output"].(string)
return knownWriters[out]
} Type guard
func isValidWriterJSON(raw json.RawMessage) bool {
var w struct{ Output string `json:"output"` }
if err := json.Unmarshal(raw, &w); err != nil { return false }
switch w.Output {
case "stderr", "stdout", "file", "net", "discard":
return true
}
return false
} Prevention
- Use exact lowercase writer names from the docs.
- In xcaddy builds, assert required writer modules are registered before shipping configs.
When it happens
Trigger: Any log (sink, default, or custom) with "writer": { "output": "unknown_thing" } or extra/missing fields that make module provisioning fail; using a writer namespace that exists only in non-standard builds.
Common situations: Typos in 'output' values ('stdout ' with space, 'Stdout' capitalized); JSON configs referencing third-party writers not registered in the binary; version drift where writer module names or schemas changed.
Related errors
- setting up sink log: %v
- setting up custom log '%s': %v
- setting up default log: %v
- server %s: logger name must not have a port: %s
- invalid action type
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/e25aae591ba4eba8.
Report an issue: GitHub.