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
- Provide a valid level value: INFO, DEBUG, ERROR, or WARNING.
- Remove the empty level entry if default logging behavior is desired.
- 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
- Never leave the level key with an empty value in YAML
- Fail fast on empty strings during config rendering
- Use schema validation (e.g. jsonschema) on logging config
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
- error while parsing config for request logging
- error while parsing config for request logging
- error while parsing config for request logging
- level field is empty
- log decision combination is not supported
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)