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

  1. Inspect the inner error (%v) to determine the specific StringMatcherFromProto failure: regex compile error, empty prefix/suffix/contains, or unrecognized matcher.
  2. Fix the StringMatcher proto: use a valid RE2 regex, non-empty prefix/suffix/contains, or a supported match pattern type.
  3. 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

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


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)