thanos-io/thanos · error

the format of level is invalid. Expected…

Error message

the format of level is invalid. Expected INFO/DEBUG/ERROR/WARNING, got this %v

What it means

validateLevel only accepts the exact uppercase strings INFO, DEBUG, ERROR, or WARNING. Any other non-empty value (including lowercase or unsupported levels like TRACE) fails with this formatted error that echoes the invalid value.

Solutions

  1. Change the level to one of INFO, DEBUG, ERROR, WARNING (uppercase, exact).
  2. Uppercase/normalize the value in config management before rendering the YAML.
  3. Add a pre-check rejecting values outside the allowed set.

Example fix

// before
level: info
// after
level: INFO
Defensive patterns

Strategy: validation

Validate before calling

var validLevels = map[string]bool{"INFO": true, "DEBUG": true, "ERROR": true, "WARNING": true}
if !validLevels[level] { return fmt.Errorf("level %q not one of INFO/DEBUG/ERROR/WARNING", level) }

Try / catch

if _, err := logging.NewGRPCOption(cfg); err != nil {
  return fmt.Errorf("log level invalid: %w", err)
}

Prevention

When it happens

Trigger: Calling NewGRPCOption or NewHTTPOption with level values like 'info', 'debug', 'WARN', 'trace', or any typo in the logging YAML config.

Common situations: Users writing lowercase levels as in other frameworks; copy-pasting TRACE (unsupported here); mixed-case values from environment substitution.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/5419da43c0133a11. Report an issue: GitHub.

Appendix: source

Thrown at pkg/logging/grpc.go:99

	if !logStart && logEnd {
		return grpc_logging.WithLogOnEvents(grpc_logging.FinishCall), nil
	}
	if logStart && logEnd {
		return grpc_logging.WithLogOnEvents(grpc_logging.StartCall, grpc_logging.FinishCall), nil
	}
	return nil, fmt.Errorf("log decision combination is not supported")
}

// validateLevel validates the list of level entries.
// Raise an error if empty or log level not in uppercase.
func validateLevel(level string) error {
	if level == "" {
		return fmt.Errorf("level field in YAML file is empty")
	}
	if level == "INFO" || level == "DEBUG" || level == "ERROR" || level == "WARNING" {
		return nil
	}
	return fmt.Errorf("the format of level is invalid. Expected INFO/DEBUG/ERROR/WARNING, got this %v", level)
}

func InterceptorLogger(l log.Logger) grpc_logging.Logger {
	return grpc_logging.LoggerFunc(func(_ context.Context, lvl grpc_logging.Level, msg string, fields ...any) {
		largs := append([]any{"msg", msg}, fields...)
		switch lvl {
		case grpc_logging.LevelDebug:
			_ = level.Debug(l).Log(largs...)
		case grpc_logging.LevelInfo:
			_ = level.Info(l).Log(largs...)
		case grpc_logging.LevelWarn:
			_ = level.Warn(l).Log(largs...)
		case grpc_logging.LevelError:
			_ = level.Error(l).Log(largs...)
		default:
			panic(fmt.Sprintf("unknown level %v", lvl))
		}
	})

View on GitHub (pinned to 35b8b99117)