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
The RLS balancer keeps an in-memory data cache keyed by request path + RLS key, and cacheSizeBytes is the hard cap on that cache. A zero or negative size makes caching impossible, so parseRLSProto rejects the config. Values above 5MB are accepted but clamped down to 5MB (maxCacheSize).
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 03255a9237)
Solutions
- Set cacheSizeBytes to a positive integer appropriate for your workload (e.g. 1000000 for ~1MB).
- Size it from expected unique keys × ~entry size; if unsure, 1–5MB is a safe starting range.
- If using xDS, verify the RLS config source (RouteLookupClusterSpecifier) is actually populating cache_size_bytes.
Example fix
// before
"routeLookupConfig": {
"lookupService": "rls.example:443",
"grpcKeybuilders": [ ... ]
}
// after
"routeLookupConfig": {
"lookupService": "rls.example:443",
"grpcKeybuilders": [ ... ],
"cacheSizeBytes": 1048576
} Defensive patterns
Strategy: validation
Validate before calling
func validateCacheSize(cfg *rlspb.RouteLookupConfig) error {
if cfg.GetCacheSizeBytes() <= 0 {
return fmt.Errorf("cache_size_bytes must be > 0")
}
return nil
} Prevention
- Make cacheSizeBytes a required field in your service config template.
- Default cacheSizeBytes to ~1MB in config generators rather than leaving it blank.
- Add a schema check that rejects non-positive cacheSizeBytes.
When it happens
Trigger: A RouteLookupConfig where cache_size_bytes is 0, negative, or simply omitted (the proto field defaults to 0). E.g. service config JSON missing the "cacheSizeBytes" key.
Common situations: Forgetting the cacheSizeBytes field when hand-writing a service config; generating configs from a template that left the field blank; assuming the library picks a default (it does not — it errors).
Related errors
- rls: stale_age is set, but max_age is not in route lookup co
- rls: invalid childPolicy: entry %v does not contain exactly
- rls: childPolicy %q with config %q does not support config p
- rls: json unmarshal failed for child policy config %q: %v
- rls: childPolicy config validation failed: %v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/65ee719294e00b30.
Report an issue: GitHub.