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

  1. Set cacheSizeBytes to a positive integer appropriate for your workload (e.g. 1000000 for ~1MB).
  2. Size it from expected unique keys × ~entry size; if unsure, 1–5MB is a safe starting range.
  3. 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

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


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