vitessio/vitess · error

log: invalid --log-level %q: %w

Error message

log: invalid --log-level %q: %w

What it means

log.Init parses the --log-level flag into an slog.Level using UnmarshalText, which accepts values like DEBUG, INFO, WARN, ERROR (case-insensitive). The library wraps the parse failure with this message when the supplied level string is not a recognized slog level.

Source

Thrown at go/vt/log/flags.go:73

func Init(fs *pflag.FlagSet) error {
	if !logStructured {
		fmt.Fprintln(os.Stderr, "WARNING: glog is deprecated and will be removed in v25")
		structured.Store(false)
		return nil
	}

	// Warn if any glog flags were explicitly set while structured logging is active,
	// since they have no effect.
	for _, name := range []string{"logtostderr", "alsologtostderr", "stderrthreshold", "log_dir", "log_backtrace_at", "vmodule", "v"} {
		if fs.Changed(name) {
			fmt.Fprintf(os.Stderr, "WARNING: --%s has no effect when structured logging is enabled, pass --log-structured=false to use glog flags\n", name)
		}
	}

	// Parse the level flag into an [slog.Level].
	var level slog.Level
	if err := level.UnmarshalText([]byte(logLevel)); err != nil {
		return fmt.Errorf("log: invalid --log-level %q: %w", logLevel, err)
	}

	l := newLogger(level)
	logger.Store(l)
	structured.Store(true)

	return nil
}

// newLogger creates a new structured logger. When the log format is "text", or we detect
// we're running tests, logs are outputted in a human-readable format (and optionally colored).
// Otherwise, or when the log format is "json", logs are outputted as machine-readable JSON.
func newLogger(level slog.Level) *slog.Logger {
	if logFormat == "text" || testing.Testing() {
		w := os.Stderr
		return slog.New(tint.NewTextHandler(w, &tint.Options{
			AddSource:  true,
			Level:      level,

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Use a valid slog level: DEBUG, INFO, WARN or ERROR (case-insensitive), e.g. --log-level=INFO.
  2. Replace legacy numeric verbosity (-v=2) with the matching named level.
  3. Check the exact error's wrapped text (the %w) to see which character/value UnmarshalText rejected.

Example fix

// before
vttablet --log-level=trace
// after
vttablet --log-level=DEBUG
Defensive patterns

Strategy: validation

Validate before calling

var lvl slog.Level
if err := lvl.UnmarshalText([]byte(logLevel)); err != nil {
	return fmt.Errorf("--log-level must be one of DEBUG|INFO|WARN|ERROR")
}

Try / catch

if err := log.Init(ctx, "vttablet"); err != nil {
	return fmt.Errorf("logging init failed: %w", err)
}

Prevention

When it happens

Trigger: Running any Vitess binary with --log-level set to an unsupported value, e.g. --log-level=verbose, --log-level=trace, --log-level=3 (numeric text is not valid here), or an empty string.

Common situations: Users copying log level names from other frameworks (e.g. 'warning' vs 'warn', 'trace'), old glog-style flags (-v=2) translated incorrectly to the new --log-level flag, typos in service startup scripts or systemd units.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/424e28c3ea6ff476. Report an issue: GitHub.