{"record":{"id":"1d279ade1004c207","repo":"grpc/grpc-go","slug":"input-stringmatcher-proto-is-nil","errorCode":null,"errorMessage":"input StringMatcher proto is nil","messagePattern":"input StringMatcher proto is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/matcher/string_matcher.go","lineNumber":99,"sourceCode":"\t\treturn nil\n\t}\n\n\ts := new(string)\n\tif ignoreCase {\n\t\t*s = strings.ToLower(*input)\n\t} else {\n\t\t*s = *input\n\t}\n\treturn s\n}\n\n// StringMatcherFromProto is a helper function to create a StringMatcher from\n// the corresponding StringMatcher proto.\n//\n// Returns a non-nil error if matcherProto is invalid.\nfunc StringMatcherFromProto(matcherProto *v3matcherpb.StringMatcher) (StringMatcher, error) {\n\tif matcherProto == nil {\n\t\treturn StringMatcher{}, errors.New(\"input StringMatcher proto is nil\")\n\t}\n\n\tmatcher := StringMatcher{ignoreCase: matcherProto.GetIgnoreCase()}\n\tswitch mt := matcherProto.GetMatchPattern().(type) {\n\tcase *v3matcherpb.StringMatcher_Exact:\n\t\tmatcher.exactMatch = newStrPtr(&mt.Exact, matcher.ignoreCase)\n\tcase *v3matcherpb.StringMatcher_Prefix:\n\t\tif matcherProto.GetPrefix() == \"\" {\n\t\t\treturn StringMatcher{}, errors.New(\"empty prefix is not allowed in StringMatcher\")\n\t\t}\n\t\tmatcher.prefixMatch = newStrPtr(&mt.Prefix, matcher.ignoreCase)\n\tcase *v3matcherpb.StringMatcher_Suffix:\n\t\tif matcherProto.GetSuffix() == \"\" {\n\t\t\treturn StringMatcher{}, errors.New(\"empty suffix is not allowed in StringMatcher\")\n\t\t}\n\t\tmatcher.suffixMatch = newStrPtr(&mt.Suffix, matcher.ignoreCase)\n\tcase *v3matcherpb.StringMatcher_SafeRegex:\n\t\tregex := matcherProto.GetSafeRegex().GetRegex()","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/matcher/string_matcher.go#L81-L117","documentation":"`StringMatcherFromProto` (internal/xds/matcher/string_matcher.go:97) constructs a StringMatcher from the Envoy StringMatcher proto. The very first check at line 98-99 rejects a nil input proto. This is a defensive guard: the function cannot read a match pattern from a nil pointer, so it fails fast with a clear message rather than dereferencing.","triggerScenarios":"Triggered when StringMatcherFromProto is called with a nil `*v3matcherpb.StringMatcher`. Call sites include header matchers, path matchers (newURLPathMatcher), and other xDS resource decoders that build matchers from proto fields which may be unset.","commonSituations":"An xDS configuration referencing a StringMatcher-typed field that was never populated (e.g. a header matcher with `string_match` left empty in YAML); a code path that pulls `GetStringMatch()` from a HeaderMatcher whose `HeaderMatchSpecifier` oneof is not the StringMatch variant, yielding nil; tests passing a literal nil.","solutions":["Ensure the proto field passed to StringMatcherFromProto is populated — initialize the StringMatcher proto with one of the match patterns (exact/prefix/suffix/contains/safe_regex).","If the field may legitimately be unset in your context, check for nil before calling and skip the matcher.","Inspect the upstream xDS configuration (header matcher, path matcher) to find the empty `string_match` block and fill it in."],"exampleFix":"// before\nsm, err := matcher.StringMatcherFromProto(nil) // err: input StringMatcher proto is nil\n\n// after\nsm, err := matcher.StringMatcherFromProto(&v3matcherpb.StringMatcher{\n    MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: \"foo\"},\n})","handlingStrategy":"type-guard","validationCode":"func safeStringMatcherFromProto(p *v3matcherpb.StringMatcher) (matcher.StringMatcher, error) {\n    if p == nil {\n        return matcher.StringMatcher{}, errors.New(\"StringMatcher proto is required\")\n    }\n    return matcher.StringMatcherFromProto(p)\n}","typeGuard":"// Narrow a oneof field before passing it to StringMatcherFromProto.\nfunc stringMatcherOrNil(hm *route_componentspb.HeaderMatcher) *v3matcherpb.StringMatcher {\n    if sm, ok := hm.HeaderMatchSpecifier.(*route_componentspb.HeaderMatcher_StringMatch); ok {\n        return sm.StringMatch\n    }\n    return nil\n}","tryCatchPattern":null,"preventionTips":["Always initialize StringMatcher protos with a concrete match pattern before sending/using them.","Guard call sites that pull a oneof field (e.g. GetStringMatch) with a type assertion to avoid nil.","Add a nil check in your config-decoding layer for any optional matcher field."],"tags":["grpc","xds","matcher","validation","nil-guard"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}