grpc/grpc-go · error

min is greater than max

Error message

min %v is greater than max %v

What it means

Returned by ringhash's parseConfig() (balancer/ringhash/config.go:55) when, after applying defaults (min=1024, max=4096 for zero values), MinRingSize > MaxRingSize. The ring cannot be built smaller than its minimum, so this ordering is invalid.

Solutions

  1. Ensure minRingSize <= maxRingSize.
  2. If you set minRingSize above the default max (4096), also set maxRingSize accordingly.
  3. Omit both to use defaults (1024/4096).

Example fix

// before: min > max (max defaults to 4096)
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"ring_hash_experimental":{"minRingSize":8192}}]}`)

// after: min <= max
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"ring_hash_experimental":{"minRingSize":8192,"maxRingSize":16384}}]}`)
Defensive patterns

Strategy: validation

Validate before calling

func validateRingSizeOrder(min, max uint64) error {
    // mimic defaults: 0 → default
    if min == 0 { min = 1024 }
    if max == 0 { max = 4096 }
    if min > max {
        return fmt.Errorf("min %d > max %d", min, max)
    }
    return nil
}

Prevention

When it happens

Trigger: The config explicitly sets minRingSize greater than maxRingSize, OR sets only maxRingSize to a value below the default min (1024). After the defaults are applied at lines 48-53, the check at line 54 fails.

Common situations: Operator swaps the two fields; sets minRingSize=8192 but leaves maxRingSize unset (defaults to 4096); xDS sends an inconsistent pair.

Related errors


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

Appendix: 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 0c51461d27)