{"record":{"id":"45fca6cadf174838","repo":"caddyserver/caddy","slug":"unrecognized-log-level-s","errorCode":null,"errorMessage":"unrecognized log level: %s","messagePattern":"unrecognized log level: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"logging.go","lineNumber":774,"sourceCode":"\t}\n\tlevel = strings.ToLower(level)\n\n\t// set up the log level\n\tswitch level {\n\tcase \"debug\":\n\t\treturn zapcore.DebugLevel, nil\n\tcase \"\", \"info\":\n\t\treturn zapcore.InfoLevel, nil\n\tcase \"warn\":\n\t\treturn zapcore.WarnLevel, nil\n\tcase \"error\":\n\t\treturn zapcore.ErrorLevel, nil\n\tcase \"panic\":\n\t\treturn zapcore.PanicLevel, nil\n\tcase \"fatal\":\n\t\treturn zapcore.FatalLevel, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unrecognized log level: %s\", level)\n\t}\n}\n\n// Log returns the current default logger.\nfunc Log() *zap.Logger {\n\tdefaultLoggerMu.RLock()\n\tdefer defaultLoggerMu.RUnlock()\n\treturn defaultLogger.logger\n}\n\n// BufferedLog sets the default logger to one that buffers\n// logs before a config is loaded.\n// Returns the buffered logger, the original default logger\n// (for flushing on errors), and the buffer core so that the\n// caller can flush the logs after the config is loaded or\n// fails to load.\nfunc BufferedLog() (*zap.Logger, *zap.Logger, *internal.LogBufferCore) {\n\tdefaultLoggerMu.Lock()","sourceCodeStart":756,"sourceCodeEnd":792,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/logging.go#L756-L792","documentation":"After placeholder replacement and lowercasing, the level string did not match any of Caddy's accepted levels: debug, info (or empty), warn, error, panic, fatal. This is a plain bad-value error, not a placeholder-resolution error.","triggerScenarios":"level set to 'trace', 'verbose', 'notice', 'WARNING' with a typo like 'warnning', or any string not in the accepted set.","commonSituations":"Porting configs from other servers whose level names differ (nginx's 'warn' works, but syslog's 'notice' does not); assuming 'trace' exists because OpenTelemetry or zap docs mention it; case is fine (it is lowercased) but spelling must match exactly.","solutions":["Use one of: DEBUG, INFO, WARN, ERROR, PANIC, FATAL (case-insensitive).","Remove the level line entirely — empty defaults to INFO.","If you need trace-level verbosity, note Caddy has no TRACE level; use DEBUG."],"exampleFix":"// before (caddyfile)\n{\n    log {\n        level TRACE\n    }\n}\n\n// after\n{\n    log {\n        level DEBUG\n    }\n}","handlingStrategy":"validation","validationCode":"var allowedLevels = map[string]bool{\"\": true, \"debug\": true, \"info\": true, \"warn\": true, \"error\": true, \"panic\": true, \"fatal\": true}\n\nfunc levelOK(s string) bool { return allowedLevels[strings.ToLower(strings.TrimSpace(s))] }","typeGuard":null,"tryCatchPattern":"if err := caddy.Validate(cfg); err != nil {\n    if strings.Contains(err.Error(), \"unrecognized log level\") {\n        // replace with debug/info/warn/error/panic/fatal\n    }\n    return err\n}","preventionTips":["Restrict level pickers/dropdowns in tooling to the six accepted values.","Remember there is no TRACE/NOTICE/VERBOSE in Caddy.","Case does not matter, spelling does."],"tags":["logging","validation","configuration"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}