grpc/grpc-go · error
server-side RPC versions are not compatible with this client
Error message
server-side RPC versions are not compatible with this client, local versions: %v, peer versions: %v
What it means
In the ALTS client handshake (alts.go:210-212), after a successful TLS-like handshake the client compares its negotiated RPC protocol versions against the peer's via checkRPCVersions. If the [min,max] version windows don't overlap, the secure connection is rejected. This is an ALTS (Google's GCP transport security) compatibility check.
Source
Thrown at credentials/alts/alts.go:212
}
opts.BoundAccessToken = g.boundAccessToken
chs, err := handshaker.NewClientHandshaker(ctx, hsConn, rawConn, opts)
if err != nil {
return nil, nil, err
}
// Close the handshaker since we have obtained a connection.
defer chs.Close()
secConn, authInfo, err := chs.ClientHandshake(ctx)
if err != nil {
return nil, nil, err
}
altsAuthInfo, ok := authInfo.(AuthInfo)
if !ok {
return nil, nil, errors.New("client-side auth info is not of type alts.AuthInfo")
}
match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
if !match {
return nil, nil, fmt.Errorf("server-side RPC versions are not compatible with this client, local versions: %v, peer versions: %v", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
}
return secConn, authInfo, nil
}
// ServerHandshake implements the server side ALTS handshaker.
func (g *altsTC) ServerHandshake(rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
if !vmOnGCP {
return nil, nil, ErrUntrustedPlatform
}
// Connecting to ALTS handshaker service.
hsConn, err := service.Dial(g.hsAddress)
if err != nil {
return nil, nil, err
}
// Do not close hsConn since it's shared with other handshakes.
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()View on GitHub (pinned to 03255a9237)
Solutions
- Align client and server gRPC (and ALTS) versions so their RPC version windows overlap.
- If ALTS isn't required, switch both sides to TLS credentials or insecure for testing.
- Run ALTS only on GCP where the handshaker service negotiates a compatible version.
Example fix
// before
creds, _ := alts.NewClientCreds(alts.ClientHandshakerOptions{...})
grpc.WithTransportCredentials(creds) // against mismatched ALTS server
// after
creds := credentials.NewTLS(&tls.Config{ServerName: "svc.example"})
grpc.WithTransportCredentials(creds) Defensive patterns
Strategy: try-catch
Try / catch
secConn, _, err := creds.ClientHandshake(ctx, authority, rawConn)
if err != nil {
if strings.Contains(err.Error(), "RPC versions are not compatible") {
log.Printf("ALTS version mismatch with peer; align gRPC versions")
}
return err
} Prevention
- Pin client and server to a compatible gRPC/ALTS release.
- Use ALTS only within a GCP fleet of known versions.
- For cross-version or external traffic, prefer TLS.
When it happens
Trigger: Using credentials/alts client-side to talk to an ALTS server whose RPC protocol version range doesn't intersect the client's compiled-in range (maxRPCVersion/minRPCVersion in alts.go). Happens across version-skewed gRPC builds.
Common situations: Client and server built from gRPC versions with different ALTS protocol versions; a non-GCP peer pretending to support ALTS; an old server that predates a protocol bump.
Related errors
- client-side RPC versions is not compatible with this server,
- negotiated unknown next_protocol %q
- received the frame length %d larger than the limit %d
- protocol %q: %v
- received frame with incorrect message type %v, expected lowe
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/0e25b22e41259924.
Report an issue: GitHub.