grpc/grpc-go · error
empty contains is not allowed in StringMatcher
Error message
empty contains is not allowed in StringMatcher
What it means
Returned by StringMatcherFromProto (string_matcher.go:124-125) for the Contains match variant when the contains substring is empty. An empty contains substring would match every string and is disallowed; this mirrors the prefix/suffix guards.
Source
Thrown at internal/xds/matcher/string_matcher.go:125
if matcherProto.GetPrefix() == "" {
return StringMatcher{}, errors.New("empty prefix is not allowed in StringMatcher")
}
matcher.prefixMatch = newStrPtr(&mt.Prefix, matcher.ignoreCase)
case *v3matcherpb.StringMatcher_Suffix:
if matcherProto.GetSuffix() == "" {
return StringMatcher{}, errors.New("empty suffix is not allowed in StringMatcher")
}
matcher.suffixMatch = newStrPtr(&mt.Suffix, matcher.ignoreCase)
case *v3matcherpb.StringMatcher_SafeRegex:
regex := matcherProto.GetSafeRegex().GetRegex()
re, err := CompileSafeRegex(regex)
if err != nil {
return StringMatcher{}, fmt.Errorf("safe_regex matcher %q is invalid", regex)
}
matcher = NewRegexStringMatcher(re)
case *v3matcherpb.StringMatcher_Contains:
if matcherProto.GetContains() == "" {
return StringMatcher{}, errors.New("empty contains is not allowed in StringMatcher")
}
matcher.containsMatch = newStrPtr(&mt.Contains, matcher.ignoreCase)
default:
return StringMatcher{}, fmt.Errorf("unrecognized string matcher: %+v", matcherProto)
}
return matcher, nil
}
// NewExactStringMatcher creates a string matcher that requires the input string
// to exactly match the pattern specified here. The match will be case
// insensitive if ignore_case is true.
func NewExactStringMatcher(pattern string, ignoreCase bool) StringMatcher {
return StringMatcher{
exactMatch: newStrPtr(&pattern, ignoreCase),
ignoreCase: ignoreCase,
}
}
View on GitHub (pinned to 03255a9237)
Solutions
- Provide a non-empty contains substring.
- If matching everything is intended, drop the matcher or use an always-allow permission.
- Add a pre-publish validation pass that rejects empty contains matchers.
Example fix
// before: { "contains": "" }
// after: { "contains": "admin" } Defensive patterns
Strategy: validation
Validate before calling
func validContainsStringMatcher(m *v3matcherpb.StringMatcher) error {
if m.GetContains() == "" {
return errors.New("contains matcher must have a non-empty substring")
}
return nil
} Prevention
- Reject empty contains substrings when generating matchers.
- Avoid templating matchers from variables that may resolve to empty.
- Add a matcher-validation pass in your control plane.
When it happens
Trigger: A StringMatcher proto whose match pattern is StringMatcher_Contains with Contains="". The switch detects the Contains case, checks GetContains()=="", and rejects it.
Common situations: Generated config with a contains variable that resolved to empty; a copy-paste of a header matcher where the substring was left blank.
Related errors
- empty prefix is not allowed in StringMatcher
- empty suffix is not allowed in StringMatcher
- input StringMatcher proto is nil
- unknown header matcher type
- filter missing name field
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/204d79aaf7c6be3d.
Report an issue: GitHub.