grpc/grpc-go · error
server-side auth info is not of type alts.AuthInfo
Error message
server-side auth info is not of type alts.AuthInfo
What it means
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.
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.
Example fix
// before: header matcher with invalid string match
header:
name: "x-custom-header"
string_match:
safe_regex:
regex: "(?<=prefix)value" // lookbehind unsupported by RE2
// after: use exact match or a valid regex
header:
name: "x-custom-header"
string_match:
exact: "expected-value" Defensive patterns
Strategy: validation
Validate before calling
// Validate header string matchers before building the engine:
func validateHeaderStringMatchers(perms []*v3rbacpb.Permission) error {
for _, perm := range perms {
if h := perm.GetHeader(); h != nil {
if sm := h.GetStringMatch(); sm != nil {
if _, err := internalmatcher.StringMatcherFromProto(sm); err != nil {
return fmt.Errorf("invalid header string matcher on %q: %w", h.GetName(), err)
}
}
}
// recurse into and/or/not as needed
}
return nil
} Try / catch
// Wrap engine construction to surface string matcher errors clearly:
engine, err := rbac.NewChainEngine(policies, "")
if err != nil && strings.Contains(err.Error(), "invalid string matcher") {
return fmt.Errorf("RBAC config rejected: header string matcher is malformed: %w", err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- message authentication failed
- rbac: header matcher for
- rbac: header matcher for
- rbac: policy.CheckedCondition is present
- rbac: Policy.condition is present
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/ecf674f4fa11fbfc.
Report an issue: GitHub.
Appendix: source
Thrown at credentials/alts/alts.go:248
defer cancel()
opts := handshaker.DefaultServerHandshakerOptions()
opts.RPCVersions = &altspb.RpcProtocolVersions{
MaxRpcVersion: maxRPCVersion,
MinRpcVersion: minRPCVersion,
}
shs, err := handshaker.NewServerHandshaker(ctx, hsConn, rawConn, opts)
if err != nil {
return nil, nil, err
}
secConn, authInfo, err := shs.ServerHandshake(ctx)
if err != nil {
return nil, nil, err
}
// Close the handshaker since we have obtained a connection.
defer shs.Close()
altsAuthInfo, ok := authInfo.(AuthInfo)
if !ok {
return nil, nil, errors.New("server-side auth info is not of type alts.AuthInfo")
}
match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
if !match {
return nil, nil, fmt.Errorf("client-side RPC versions is not compatible with this server, local versions: %v, peer versions: %v", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
}
return secConn, authInfo, nil
}
func (g *altsTC) Info() credentials.ProtocolInfo {
return *g.info
}
func (g *altsTC) Clone() credentials.TransportCredentials {
info := *g.info
var accounts []string
if g.accounts != nil {
accounts = make([]string, len(g.accounts))
copy(accounts, g.accounts)View on GitHub (pinned to 0c51461d27)