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 function

View on GitHub (pinned to 35bff19146)

Solutions

  1. Use one of: debug (or trace), info (or print), warn, error (or fatal/panic).
  2. Prefer ParseLevelOr with an empty string so the default level applies.
  3. Trim the env value before parsing; map "warning" to "warn" in your config tooling.
  4. 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

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.