googleapis/mcp-toolbox · error

invalid log level

Error message

invalid log level

What it means

SeverityToLevel maps the library's Severity constants (Debug, Info, Warn, Error) to slog.Level values. It returns this error when the input severity string matches none of the known cases, so the logger cannot translate it into a slog level. This guards against typo'd or future-unknown severity values passed to NewStdLogger/NewStructuredLogger.

Source

Thrown at internal/log/log.go:110

	Debug = "DEBUG"
	Info  = "INFO"
	Warn  = "WARN"
	Error = "ERROR"
)

// Returns severity level based on string.
func SeverityToLevel(s string) (slog.Level, error) {
	switch strings.ToUpper(s) {
	case Debug:
		return slog.LevelDebug, nil
	case Info:
		return slog.LevelInfo, nil
	case Warn:
		return slog.LevelWarn, nil
	case Error:
		return slog.LevelError, nil
	default:
		return slog.Level(-5), fmt.Errorf("invalid log level")
	}
}

// Returns severity string based on level.
func levelToSeverity(s string) (string, error) {
	switch s {
	case slog.LevelDebug.String():
		return Debug, nil
	case slog.LevelInfo.String():
		return Info, nil
	case slog.LevelWarn.String():
		return Warn, nil
	case slog.LevelError.String():
		return Error, nil
	default:
		return "", fmt.Errorf("invalid slog level")
	}
}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Use one of the supported severity values exactly: Debug, Info, Warn, Error (matching the Severity constants' String() values).
  2. Normalize/trim the input (strings.TrimSpace, strings.ToUpper) before passing it to SeverityToLevel or the logger constructors.
  3. Inspect the error returned from NewStdLogger/NewStructuredLogger at startup and fail fast with a message listing valid levels.

Example fix

// before
logger, err := log.NewStructuredLogger("warning", os.Stderr)
// after
logger, err := log.NewStructuredLogger("WARN", os.Stderr)
Defensive patterns

Strategy: validation

Validate before calling

func validSeverity(s string) bool {
	switch strings.ToUpper(strings.TrimSpace(s)) {
	case "DEBUG", "INFO", "WARN", "ERROR":
		return true
	}
	return false
}
if !validSeverity(flagLevel) {
	return fmt.Errorf("--log-level must be one of DEBUG|INFO|WARN|ERROR, got %q", flagLevel)
}

Type guard

func isSeverity(s string) bool {
	switch log.Severity(s) {
	case log.Debug, log.Info, log.Warn, log.Error:
		return true
	}
	return false
}

Try / catch

logger, err := log.NewStructuredLogger(level, os.Stderr)
if err != nil {
	if strings.Contains(err.Error(), "invalid log level") {
		log.Fatalf("invalid --log-level %q; use DEBUG|INFO|WARN|ERROR", level)
	}
	log.Fatal(err)
}

Prevention

When it happens

Trigger: Calling SeverityToLevel (directly or via NewStdLogger/NewStructuredLogger/server startup logging config) with a severity string other than "DEBUG","INFO","WARN","ERROR" — e.g. "warning", "verbose", an empty string, or a lowercased value.

Common situations: A CLI flag --log-level=warning is used instead of WARN; an env var like LOG_SEVERITY is unset or contains trailing whitespace; a user invents a level like TRACE that the library does not support.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/61a1057fdcac7b07. Report an issue: GitHub.