{"record":{"id":"65ee719294e00b30","repo":"grpc/grpc-go","slug":"rls-cache-size-bytes-must-be-set-to-a-non-zero-va","errorCode":null,"errorMessage":"rls: cache_size_bytes must be set to a non-zero value: %+v","messagePattern":"rls: cache_size_bytes must be set to a non-zero value: %\\+v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":265,"sourceCode":"\n\tif staleAgeSet && !maxAgeSet {\n\t\treturn nil, fmt.Errorf(\"rls: stale_age is set, but max_age is not in route lookup config %+v\", rlsProto)\n\t}\n\tif staleAge > maxMaxAge {\n\t\tstaleAge = maxMaxAge\n\t}\n\tif !staleAgeSet && maxAge > maxMaxAge {\n\t\tmaxAge = maxMaxAge\n\t}\n\tif staleAge > maxAge {\n\t\tstaleAge = maxAge\n\t}\n\n\t// `cache_size_bytes` field must have a value greater than 0, and if its\n\t// value is greater than 5M, we cap it at 5M\n\tcacheSizeBytes := rlsProto.GetCacheSizeBytes()\n\tif cacheSizeBytes <= 0 {\n\t\treturn nil, fmt.Errorf(\"rls: cache_size_bytes must be set to a non-zero value: %+v\", rlsProto)\n\t}\n\tif cacheSizeBytes > maxCacheSize {\n\t\tlogger.Infof(\"rls: cache_size_bytes %v is too large, setting it to: %v\", cacheSizeBytes, maxCacheSize)\n\t\tcacheSizeBytes = maxCacheSize\n\t}\n\treturn &lbConfig{\n\t\tkbMap:                kbMap,\n\t\tlookupService:        lookupService,\n\t\tlookupServiceTimeout: lookupServiceTimeout,\n\t\tmaxAge:               maxAge,\n\t\tstaleAge:             staleAge,\n\t\tcacheSizeBytes:       cacheSizeBytes,\n\t\tdefaultTarget:        rlsProto.GetDefaultTarget(),\n\t}, nil\n}\n\n// parseChildPolicyConfigs iterates through the list of child policies and picks\n// the first registered policy and validates its config.","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/config.go#L247-L283","documentation":"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).","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before\n\"routeLookupConfig\": {\n  \"lookupService\": \"rls.example:443\",\n  \"grpcKeybuilders\": [ ... ]\n}\n// after\n\"routeLookupConfig\": {\n  \"lookupService\": \"rls.example:443\",\n  \"grpcKeybuilders\": [ ... ],\n  \"cacheSizeBytes\": 1048576\n}","handlingStrategy":"validation","validationCode":"func validateCacheSize(cfg *rlspb.RouteLookupConfig) error {\n    if cfg.GetCacheSizeBytes() <= 0 {\n        return fmt.Errorf(\"cache_size_bytes must be > 0\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["rls","service-config","config-validation","go","grpc","cache"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}