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

Returned at credentials/alts/alts.go:246-249 (the server-side analogue of error 14) when shs.ServerHandshake succeeds but the AuthInfo it returns fails the `authInfo.(AuthInfo)` type assertion. The server-side ALTS handshake produced an AuthInfo that is not the expected alts.AuthInfo type.

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 03255a9237)

Solutions

  1. Upgrade the grpc + alts + handshaker module set together and run go mod tidy.
  2. Make sure no middleware rewraps the net.Conn/AuthInfo returned by ServerHandshake before gRPC reads it.
  3. Confirm you are on GCP using the real handshaker service (vmOnGCP true).
  4. Add an integration test on GCP that asserts AuthInfoFromContext(ctx) returns non-nil alts.AuthInfo.

Example fix

// before — server registers ALTS but a Conn wrapper swaps AuthInfo
creds := alts.NewServerCreds(opts)
srv := grpc.NewServer(grpc.Creds(creds))
// a transport interceptor replaced AuthInfo -> 'server-side auth info is not of type alts.AuthInfo'

// after — pass rawConn/AuthInfo through unmodified
creds := alts.NewServerCreds(opts)
srv := grpc.NewServer(grpc.Creds(creds))
Defensive patterns

Strategy: type-guard

Validate before calling

// Server-side: confirm ALTS creds are registered before relying on ALTS AuthInfo
srv := grpc.NewServer(grpc.Creds(alts.NewServerCreds(alts.DefaultServerOptions())))

Type guard

func isALTSAuthInfo(ai credentials.AuthInfo) bool {
    _, ok := ai.(alts.AuthInfo)
    return ok
}

Try / catch

ai, err := alts.AuthInfoFromContext(ctx)
if err != nil {
    // likely non-ALTS transport or module skew; check creds + module versions
}

Prevention

When it happens

Trigger: Server-side altsTC.ServerHandshake finishes the handshaker exchange, but the returned AuthInfo does not implement alts.AuthInfo. Same root causes as the client side: handshaker/proto module skew or a tampered rawConn/AuthInfo path.

Common situations: Version mismatch between the server's grpc/alts modules and the ALTS handshaker; outdated vendored alts; a proxy/in-process wrapper that replaces AuthInfo on the server transport.

Related errors


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