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
- 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).
- Populate the field in the control-plane RLS resource template with a sane non-zero default.
- 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
- Always set cache_size_bytes; there is no default.
- Pick a value relative to expected distinct keys (client caps at 5 MB).
- Flag zero cache_size_bytes as a config-lint error.
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
- rls: bad control channel service config
- rls: bad RouteLookupConfig proto %+v
- rls: childPolicyConfigTargetFieldName field is not set in…
- rls: empty lookup_service in route lookup config %+v
- rls: invalid childPolicy: entry
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)