grpc/grpc-go · error

min %v is greater than max %v

Error message

min %v is greater than max %v

What it means

Returned by ringhash.parseConfig (config.go:54-56) when, after applying defaults (min->1024, max->4096 when zero) and the upper-bound clamp, MinRingSize ends up greater than MaxRingSize. The ring requires min <= max so that the actual ring size is chosen uniformly in [min,max]. The %v values are the final min and max.

Source

Thrown at balancer/ringhash/config.go:55

func parseConfig(c json.RawMessage) (*iringhash.LBConfig, error) {
	var cfg iringhash.LBConfig
	if err := json.Unmarshal(c, &cfg); err != nil {
		return nil, err
	}
	if cfg.MinRingSize > ringHashSizeUpperBound {
		return nil, fmt.Errorf("min_ring_size value of %d is greater than max supported value %d for this field", cfg.MinRingSize, ringHashSizeUpperBound)
	}
	if cfg.MaxRingSize > ringHashSizeUpperBound {
		return nil, fmt.Errorf("max_ring_size value of %d is greater than max supported value %d for this field", cfg.MaxRingSize, ringHashSizeUpperBound)
	}
	if cfg.MinRingSize == 0 {
		cfg.MinRingSize = defaultMinSize
	}
	if cfg.MaxRingSize == 0 {
		cfg.MaxRingSize = defaultMaxSize
	}
	if cfg.MinRingSize > cfg.MaxRingSize {
		return nil, fmt.Errorf("min %v is greater than max %v", cfg.MinRingSize, cfg.MaxRingSize)
	}
	if cfg.MinRingSize > envconfig.RingHashCap {
		cfg.MinRingSize = envconfig.RingHashCap
	}
	if cfg.MaxRingSize > envconfig.RingHashCap {
		cfg.MaxRingSize = envconfig.RingHashCap
	}
	if !envconfig.RingHashSetRequestHashKey {
		cfg.RequestHashHeader = ""
	}
	if cfg.RequestHashHeader != "" {
		cfg.RequestHashHeader = strings.ToLower(cfg.RequestHashHeader)
		// See rules in https://github.com/grpc/proposal/blob/master/A76-ring-hash-improvements.md#explicitly-setting-the-request-hash-key
		if err := metadata.ValidateKey(cfg.RequestHashHeader); err != nil {
			return nil, fmt.Errorf("invalid requestHashHeader %q: %v", cfg.RequestHashHeader, err)
		}
		if strings.HasSuffix(cfg.RequestHashHeader, "-bin") {
			return nil, fmt.Errorf("invalid requestHashHeader %q: key must not end with \"-bin\"", cfg.RequestHashHeader)

View on GitHub (pinned to 03255a9237)

Solutions

  1. Ensure minRingSize <= maxRingSize in the config.
  2. Prefer relying on defaults (omit both) unless you have a measured reason to tune them.
  3. If from xDS, fix minimumRingSize/maximumRingSize ordering in the Cluster resource.

Example fix

// before
raw := `{"minRingSize": 8192, "maxRingSize": 4096}` // min > max -> error

// after
raw := `{"minRingSize": 2048, "maxRingSize": 8192}`
Defensive patterns

Strategy: validation

Validate before calling

func validateRingSizeOrder(raw []byte) error {
    var c struct{ MinRingSize, MaxRingSize uint64 `json:"minRingSize"` } // illustrative
    var full struct {
        MinRingSize uint64 `json:"minRingSize"`
        MaxRingSize uint64 `json:"maxRingSize"`
    }
    _ = json.Unmarshal(raw, &full)
    if full.MinRingSize != 0 && full.MaxRingSize != 0 && full.MinRingSize > full.MaxRingSize {
        return fmt.Errorf("min %d > max %d", full.MinRingSize, full.MaxRingSize)
    }
    return nil
}

Prevention

When it happens

Trigger: Config explicitly sets minRingSize larger than maxRingSize (e.g. min=8192, max=4096). Note: leaving both zero is fine because defaults satisfy min<=max; this only fires when an explicit inversion exists.

Common situations: Swapping the two fields when hand-writing config. xDS control plane emitting inverted min/max. Defaults masking part of the problem (only the explicit inversion triggers it).

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/61d89c82116e4cc2. Report an issue: GitHub.