thanos-io/thanos · error

level field in YAML file is empty

Error message

level field in YAML file is empty

What it means

validateLevel checks the 'level' string from the logging YAML config. An empty string means the level field was not provided at all, so validation fails with this error before the value is checked against allowed levels.

Solutions

  1. Provide a valid level value: INFO, DEBUG, ERROR, or WARNING.
  2. Remove the empty level entry if default logging behavior is desired.
  3. Validate the YAML non-empty before passing to NewGRPCOption/NewHTTPOption.

Example fix

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

Strategy: validation

Validate before calling

if level == "" { return fmt.Errorf("logging level must be a non-empty string") }

Try / catch

if _, err := logging.NewHTTPOption(cfg); err != nil {
  return fmt.Errorf("http logging config invalid: %w", err)
}

Prevention

When it happens

Trigger: Calling NewGRPCOption or NewHTTPOption with a config whose level entry is empty — e.g. 'level: ""' or a level list containing an empty element.

Common situations: YAML key present with no value; templating that substituted an empty string; users commenting out the level value but keeping the key.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at pkg/logging/grpc.go:94

// getGRPCLoggingOption returns the logging ENUM based on logStart and logEnd values.
func getGRPCLoggingOption(logStart, logEnd bool) (grpc_logging.Option, error) {
	if !logStart && !logEnd {
		return grpc_logging.WithLogOnEvents(), nil
	}
	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:

View on GitHub (pinned to 35b8b99117)