grpc/grpc-go · error

rls: cache_size_bytes must be set to a non-zero value: %+v

Error message

rls: cache_size_bytes must be set to a non-zero value: %+v

What it means

Emitted from parseRLSProto (config.go:265) when RouteLookupConfig.cache_size_bytes is <= 0. The RLS data cache must have a positive size; the client also caps it at maxCacheSize (5 MB). There is no default, so zero is an error.

Solutions

  1. Set cache_size_bytes to a positive value appropriate for your fan-out, e.g. 100000 (it will be capped at 5242880 if too large).
  2. Populate the field in the control-plane RLS resource template with a sane non-zero default.
  3. Treat cache size as required input during config validation in your deployment pipeline.

Example fix

// before
"routeLookupConfig": { "cacheSizeBytes": 0, ... }

// after
"routeLookupConfig": { "cacheSizeBytes": 100000, ... }
Defensive patterns

Strategy: validation

Validate before calling

func validateCacheSize(b int64) error {
    if b <= 0 {
        return errors.New("cache_size_bytes must be greater than 0")
    }
    return nil
}

Type guard

func cacheSizeIsPositive(b int64) bool { return b > 0 }

Prevention

When it happens

Trigger: cache_size_bytes omitted (proto default 0) or set to a non-positive value in the RouteLookupConfig.

Common situations: Forgetting to set cache size in a hand-authored config; xDS RLS resource where the field was never populated; an operator setting it to 0 expecting 'unlimited'.

Related errors


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

Appendix: source

Thrown at balancer/rls/config.go:265

	if staleAgeSet && !maxAgeSet {
		return nil, fmt.Errorf("rls: stale_age is set, but max_age is not in route lookup config %+v", rlsProto)
	}
	if staleAge > maxMaxAge {
		staleAge = maxMaxAge
	}
	if !staleAgeSet && maxAge > maxMaxAge {
		maxAge = maxMaxAge
	}
	if staleAge > maxAge {
		staleAge = maxAge
	}

	// `cache_size_bytes` field must have a value greater than 0, and if its
	// value is greater than 5M, we cap it at 5M
	cacheSizeBytes := rlsProto.GetCacheSizeBytes()
	if cacheSizeBytes <= 0 {
		return nil, fmt.Errorf("rls: cache_size_bytes must be set to a non-zero value: %+v", rlsProto)
	}
	if cacheSizeBytes > maxCacheSize {
		logger.Infof("rls: cache_size_bytes %v is too large, setting it to: %v", cacheSizeBytes, maxCacheSize)
		cacheSizeBytes = maxCacheSize
	}
	return &lbConfig{
		kbMap:                kbMap,
		lookupService:        lookupService,
		lookupServiceTimeout: lookupServiceTimeout,
		maxAge:               maxAge,
		staleAge:             staleAge,
		cacheSizeBytes:       cacheSizeBytes,
		defaultTarget:        rlsProto.GetDefaultTarget(),
	}, nil
}

// parseChildPolicyConfigs iterates through the list of child policies and picks
// the first registered policy and validates its config.

View on GitHub (pinned to 0c51461d27)