grpc/grpc-go · error
RLS call throttled at client side
Error message
RLS call throttled at client side
What it means
Thrown by StringMatcherFromProto when a StringMatcher's SafeRegex match pattern fails to compile as a Go RE2 regular expression via regexp.Compile. The xDS StringMatcher SafeRegex variant expects an RE2-compatible pattern; if the pattern contains unsupported syntax (e.g., backreferences, lookahead) or is malformed, compilation fails. The error wraps the offending pattern for diagnosis.
Source
Thrown at balancer/rls/picker.go:40
"errors"
"fmt"
"strings"
"sync/atomic"
"time"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/balancer/rls/internal/keys"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/connectivity"
estats "google.golang.org/grpc/experimental/stats"
internalgrpclog "google.golang.org/grpc/internal/grpclog"
rlspb "google.golang.org/grpc/internal/proto/grpc_lookup_v1"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
var (
errRLSThrottled = errors.New("RLS call throttled at client side")
// Function to compute data cache entry size.
computeDataCacheEntrySize = dcEntrySize
)
// exitIdler wraps the only method on the BalancerGroup that the picker calls.
type exitIdler interface {
ExitIdleOne(id string)
}
// rlsPicker selects the subConn to be used for a particular RPC. It does not
// manage subConns directly and delegates to pickers provided by child policies.
type rlsPicker struct {
// The keyBuilder map used to generate RLS keys for the RPC. This is built
// by the LB policy based on the received ServiceConfig.
kbm keys.BuilderMap
// Endpoint from the user's original dial target. Used to set the `host_key`
// field in `extra_keys`.View on GitHub (pinned to 0c51461d27)
Solutions
- Test the regex against Go's regexp package: if regexp.MustCompile(pattern) fails locally, the pattern is incompatible — rewrite it to RE2 syntax.
- Remove backreferences, lookahead, and lookbehind constructs; RE2 only supports leftmost-longest matching without them.
- If the pattern is used for simple matching, consider switching the StringMatcher to exact, prefix, suffix, or contains variants which do not require regex compilation.
Example fix
// before (control plane config with RE2-incompatible regex):
string_matcher:
safe_regex:
regex: "^(foo)\1$" // backreference - unsupported by RE2
// after:
string_matcher:
safe_regex:
regex: "^foofoo$" // equivalent, RE2-compatible Defensive patterns
Strategy: validation
Validate before calling
// Pre-compile regex patterns to verify RE2 compatibility before sending them in xDS:
func validateSafeRegex(pattern string) error {
if _, err := regexp.Compile(pattern); err != nil {
return fmt.Errorf("regex %q is not RE2-compatible: %w", pattern, err)
}
return nil
}
// Usage before building the StringMatcher proto:
for _, p := range policies {
for _, perm := range p.GetPermissions() {
if h := perm.GetHeader(); h != nil {
if sm := h.GetStringMatch(); sm != nil {
if sr := sm.GetSafeRegex(); sr != nil {
if err := validateSafeRegex(sr.GetRegex()); err != nil {
return err
}
}
}
}
}
} Prevention
- Test all regex patterns with Go's regexp package before embedding them in xDS configs.
- Avoid backreferences ((.*)\1), lookahead (?=), and lookbehind (?<=) — use explicit alternation or anchoring instead.
- Prefer exact/prefix/suffix/contains matchers over regex when possible; they are faster and cannot fail at compile time.
When it happens
Trigger: An xDS resource (route match, RBAC header matcher, path matcher, authenticated principal matcher) specifies a string matcher with safe_regex whose regex field is syntactically invalid or uses PCRE-only features not supported by Go's RE2 engine. For example, a pattern like '(?P<name>...)\k<name>' (named backreference) will fail because RE2 does not support backreferences.
Common situations: Patterns ported from Envoy's default regex engine that have wider syntax support. A control plane that passes user-supplied regex strings without validation. Patterns with unescaped special characters or mismatched parentheses. An RE2-incompatible construct like \1 backreferences or lookbehind (?<=...).
Related errors
- weighted-target: no targets to pick from
- input StringMatcher proto is nil
- empty prefix is not allowed in StringMatcher
- empty suffix is not allowed in StringMatcher
- empty contains is not allowed in StringMatcher
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/639d77e09985bc04.
Report an issue: GitHub.