argoproj/argo-workflows · error
invalid log level: %s
Error message
invalid log level: %s
What it means
ParseLevel converts a string into the Level enum. Valid values are trace/debug, info/print, warn, and error/fatal/panic (the latter two kept only as legacy aliases). Any other string returns this error; legacy names are silently mapped, but truly unknown ones are rejected.
Source
Thrown at util/logging/logging.go:83
if s == "" {
return defaultLevel, nil
}
return ParseLevel(s)
}
// ParseLevel parses a string into a Level enum
func ParseLevel(s string) (Level, error) {
switch strings.ToLower(s) {
case "trace", "debug": // trace is a legacy removed level
return Debug, nil
case "info", "print": // print is a legacy removed level
return Info, nil
case "warn":
return Warn, nil
case "error", "fatal", "panic": // fatal and panic are legacy removed levels
return Error, nil
default:
return "", fmt.Errorf("invalid log level: %s", s)
}
}
var (
lock = sync.RWMutex{}
exitFunc func(int)
globalHooks []Hook
)
// SetExitFunc sets the exit function for testing purposes
func SetExitFunc(f func(int)) {
lock.Lock()
defer lock.Unlock()
exitFunc = f
}
// GetExitFunc returns the current exit functionView on GitHub (pinned to 35bff19146)
Solutions
- Use one of: debug (or trace), info (or print), warn, error (or fatal/panic).
- Prefer ParseLevelOr with an empty string so the default level applies.
- Trim the env value before parsing; map "warning" to "warn" in your config tooling.
- Pin the level in deployment templates to a known literal instead of free-form input.
Example fix
// before
level, err := logging.ParseLevel("warning")
// after
level, err := logging.ParseLevelOr(strings.TrimSpace(os.Getenv("ARGO_LOGLEVEL")), logging.Info) Defensive patterns
Strategy: validation
Validate before calling
var validLevels = map[string]bool{"debug": true, "trace": true, "info": true, "print": true, "warn": true, "error": true, "fatal": true, "panic": true}
func logLevelValid(s string) bool { return s == "" || validLevels[strings.ToLower(strings.TrimSpace(s))] } Try / catch
lvl, err := logging.ParseLevelOr(strings.TrimSpace(raw), logging.Info)
if err != nil {
log.Printf("bad log level %q, defaulting to info", raw)
lvl = logging.Info
} Prevention
- Whitelist levels (debug/info/warn/error) in deployment templates and Helm values.
- Map legacy aliases from other loggers (warning→warn, verbose→debug) in config tooling.
- Trim env input; use ParseLevelOr with a default.
When it happens
Trigger: Setting the log level env var (e.g. ARGO_LOGLEVEL) or calling ParseLevel/ContextWithLogger with values like "verbose", "warning", "notice", "5", or "INFO " with stray whitespace.
Common situations: Migrating from logrus configs where "warning" was legal; numeric levels from log15/zap setups; Helm values templating an unset variable into a literal like "<nil>".
Related errors
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/4b2cd93ad71ac920.
Report an issue: GitHub.