{"record":{"id":"ecf674f4fa11fbfc","repo":"grpc/grpc-go","slug":"server-side-auth-info-is-not-of-type-alts-authinfo","errorCode":null,"errorMessage":"server-side auth info is not of type alts.AuthInfo","messagePattern":"server-side auth info is not of type alts\\.AuthInfo","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/alts/alts.go","lineNumber":248,"sourceCode":"\tdefer cancel()\n\topts := handshaker.DefaultServerHandshakerOptions()\n\topts.RPCVersions = &altspb.RpcProtocolVersions{\n\t\tMaxRpcVersion: maxRPCVersion,\n\t\tMinRpcVersion: minRPCVersion,\n\t}\n\tshs, err := handshaker.NewServerHandshaker(ctx, hsConn, rawConn, opts)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tsecConn, authInfo, err := shs.ServerHandshake(ctx)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\t// Close the handshaker since we have obtained a connection.\n\tdefer shs.Close()\n\taltsAuthInfo, ok := authInfo.(AuthInfo)\n\tif !ok {\n\t\treturn nil, nil, errors.New(\"server-side auth info is not of type alts.AuthInfo\")\n\t}\n\tmatch, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())\n\tif !match {\n\t\treturn nil, nil, fmt.Errorf(\"client-side RPC versions is not compatible with this server, local versions: %v, peer versions: %v\", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())\n\t}\n\treturn secConn, authInfo, nil\n}\n\nfunc (g *altsTC) Info() credentials.ProtocolInfo {\n\treturn *g.info\n}\n\nfunc (g *altsTC) Clone() credentials.TransportCredentials {\n\tinfo := *g.info\n\tvar accounts []string\n\tif g.accounts != nil {\n\t\taccounts = make([]string, len(g.accounts))\n\t\tcopy(accounts, g.accounts)","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/alts/alts.go#L230-L266","documentation":"Thrown by newHeaderMatcher when StringMatcherFromProto fails to construct a StringMatcher from a HeaderMatcher's StringMatch field. The inner error from StringMatcherFromProto (which could be an invalid regex, an empty prefix/suffix/contains, an unrecognized matcher type, or a nil proto) is wrapped with the offending proto for context. This indicates the header string match configuration inside an RBAC permission or principal is malformed.","triggerScenarios":"An RBAC policy uses a header matcher with the StringMatch variant (HeaderMatcher_StringMatch), and the enclosed StringMatcher proto is invalid — e.g., its SafeRegex has an RE2-incompatible pattern, its Prefix/Suffix/Contains is empty, or its MatchPattern oneof is unset or unrecognized. The error originates in StringMatcherFromProto and propagates through newHeaderMatcher.","commonSituations":"A header string match with a regex containing unsupported syntax (backreferences, lookahead). A StringMatcher with Prefix/Suffix/Contains set to an empty string, which StringMatcherFromProto explicitly rejects. A StringMatcher whose match pattern oneof is not set (nil MatchPattern), which hits the default 'unrecognized string matcher' case. Control plane version skew introducing a new StringMatcher variant.","solutions":["Inspect the inner error (%v) to determine the specific StringMatcherFromProto failure: regex compile error, empty prefix/suffix/contains, or unrecognized matcher.","Fix the StringMatcher proto: use a valid RE2 regex, non-empty prefix/suffix/contains, or a supported match pattern type.","If the header match is for a simple value, switch to ExactMatch or PresentMatch variants of HeaderMatcher which are simpler and less error-prone."],"exampleFix":"// before: header matcher with invalid string match\nheader:\n  name: \"x-custom-header\"\n  string_match:\n    safe_regex:\n      regex: \"(?<=prefix)value\"  // lookbehind unsupported by RE2\n\n// after: use exact match or a valid regex\nheader:\n  name: \"x-custom-header\"\n  string_match:\n    exact: \"expected-value\"","handlingStrategy":"validation","validationCode":"// Validate header string matchers before building the engine:\nfunc validateHeaderStringMatchers(perms []*v3rbacpb.Permission) error {\n    for _, perm := range perms {\n        if h := perm.GetHeader(); h != nil {\n            if sm := h.GetStringMatch(); sm != nil {\n                if _, err := internalmatcher.StringMatcherFromProto(sm); err != nil {\n                    return fmt.Errorf(\"invalid header string matcher on %q: %w\", h.GetName(), err)\n                }\n            }\n        }\n        // recurse into and/or/not as needed\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Wrap engine construction to surface string matcher errors clearly:\nengine, err := rbac.NewChainEngine(policies, \"\")\nif err != nil && strings.Contains(err.Error(), \"invalid string matcher\") {\n    return fmt.Errorf(\"RBAC config rejected: header string matcher is malformed: %w\", err)\n}","preventionTips":["Test all regex patterns in header string matchers with Go's regexp.Compile before using them.","Avoid empty prefix/suffix/contains values in StringMatcher protos.","Prefer ExactMatch or PresentMatch header variants for simple checks to avoid StringMatcher pitfalls."],"tags":["xds","rbac","grpc","header-matcher","string-matcher","validation"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}