grpc/grpc-go · error

input StringMatcher proto is nil

Error message

input StringMatcher proto is nil

What it means

Returned by StringMatcherFromProto (string_matcher.go:98-99) when the caller passes a nil *StringMatcher proto. The builder cannot derive a match pattern from a nil message, so it fails immediately rather than panicking on the subsequent GetMatchPattern switch.

Source

Thrown at internal/xds/matcher/string_matcher.go:99

		return nil
	}

	s := new(string)
	if ignoreCase {
		*s = strings.ToLower(*input)
	} else {
		*s = *input
	}
	return s
}

// StringMatcherFromProto is a helper function to create a StringMatcher from
// the corresponding StringMatcher proto.
//
// Returns a non-nil error if matcherProto is invalid.
func StringMatcherFromProto(matcherProto *v3matcherpb.StringMatcher) (StringMatcher, error) {
	if matcherProto == nil {
		return StringMatcher{}, errors.New("input StringMatcher proto is nil")
	}

	matcher := StringMatcher{ignoreCase: matcherProto.GetIgnoreCase()}
	switch mt := matcherProto.GetMatchPattern().(type) {
	case *v3matcherpb.StringMatcher_Exact:
		matcher.exactMatch = newStrPtr(&mt.Exact, matcher.ignoreCase)
	case *v3matcherpb.StringMatcher_Prefix:
		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()

View on GitHub (pinned to 03255a9237)

Solutions

  1. Ensure the StringMatcher proto is fully populated (set exact/prefix/suffix/contains/safe_regex) before passing it in.
  2. Null-check the matcher pointer at the call site and skip or fail with a clearer upstream error.
  3. Fix the xDS/route configuration that produced an empty StringMatcher.

Example fix

// before
sm, err := matcher.StringMatcherFromProto(nil) // error
// after
if protoCfg == nil {
    return errors.New("string_matcher must be configured")
}
sm, err := matcher.StringMatcherFromProto(protoCfg)
Defensive patterns

Strategy: type-guard

Type guard

func isNonNilStringMatcher(m *v3matcherpb.StringMatcher) bool {
    return m != nil
}
// guard the call site:
//   if !isNonNilStringMatcher(sm) { return errors.New("string matcher required") }

Prevention

When it happens

Trigger: A header/path/rbac matcher configuration that references a StringMatcher field which was never populated, so the pointer passed to StringMatcherFromProto is nil. Commonly reached via newHeaderMatcher (StringMatch case) or newURLPathMatcher when the upstream proto field is unset.

Common situations: An xDS RBAC or route rule that declares a string matcher but leaves the matcher message empty; programmatic matcher construction that forwards an uninitialised proto field; control plane omitting the matcher body.

Related errors


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