thanos-io/thanos · error

log decision combination is not supported

Error message

log decision combination is not supported

What it means

getGRPCLoggingOption maps the logStart/logEnd booleans onto grpc_logging.WithLogOnEvents values. All supported combinations (neither, end-only, start-only, both) are handled by the preceding ifs; reaching the final return means the inputs were invalid (e.g. a start-only combination rejected upstream), so the function reports an unsupported decision combination.

Solutions

  1. Set both logStart and logEnd to true, or both false, or logEnd only.
  2. Check NewGRPCOption inputs so unsupported start-only combinations are filtered before calling.
  3. Use the documented YAML decision keys instead of constructing options manually.

Example fix

// before
NewGRPCOption(level, logStart=true, logEnd=false) // unsupported in this path
// after
NewGRPCOption(level, logStart=true, logEnd=true)
Defensive patterns

Strategy: validation

Validate before calling

if !(logStart == logEnd || (logEnd && !logStart)) {
  return fmt.Errorf("only end-only or start+end logging supported")
}

Try / catch

opt, err := logging.NewGRPCOption(level, logStart, logEnd)
if err != nil { return nil, fmt.Errorf("unsupported log decision: %w", err) }

Prevention

When it happens

Trigger: Calling NewGRPCOption with a decision combination that falls through all if-branches — practically, logStart=true with logEnd=false after prior validations did not reject it, or misuse of the internal API.

Common situations: Programmatic construction of logging options passing booleans in the wrong order, or YAML where only logStart is enabled in a code path that does not support it.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at pkg/logging/grpc.go:87

		globalLevel = protocolOptionConfig.Level
		globalStart = protocolOptionConfig.Decision.LogStart
		globalEnd = protocolOptionConfig.Decision.LogEnd
	}
	return globalLevel, globalStart, globalEnd, nil
}

// 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 {

View on GitHub (pinned to 35b8b99117)