{"record":{"id":"0e25b22e41259924","repo":"grpc/grpc-go","slug":"server-side-rpc-versions-are-not-compatible-with-t","errorCode":null,"errorMessage":"server-side RPC versions are not compatible with this client, local versions: %v, peer versions: %v","messagePattern":"server-side RPC versions are not compatible with this client, local versions: (.+?), peer versions: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/alts/alts.go","lineNumber":212,"sourceCode":"\t}\n\topts.BoundAccessToken = g.boundAccessToken\n\tchs, err := handshaker.NewClientHandshaker(ctx, hsConn, rawConn, opts)\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 chs.Close()\n\tsecConn, authInfo, err := chs.ClientHandshake(ctx)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\taltsAuthInfo, ok := authInfo.(AuthInfo)\n\tif !ok {\n\t\treturn nil, nil, errors.New(\"client-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(\"server-side RPC versions are not compatible with this client, local versions: %v, peer versions: %v\", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())\n\t}\n\treturn secConn, authInfo, nil\n}\n\n// ServerHandshake implements the server side ALTS handshaker.\nfunc (g *altsTC) ServerHandshake(rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {\n\tif !vmOnGCP {\n\t\treturn nil, nil, ErrUntrustedPlatform\n\t}\n\t// Connecting to ALTS handshaker service.\n\thsConn, err := service.Dial(g.hsAddress)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\t// Do not close hsConn since it's shared with other handshakes.\n\n\tctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)\n\tdefer cancel()","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/alts/alts.go#L194-L230","documentation":"Returned during an ALTS client handshake (alts.ClientHandshake) after the handshake completes successfully, when checkRPCVersions reports that the locally advertised RPC protocol version range does not overlap with the peer (server) reported range. The local range is hardcoded to [2.1, 2.1]. A mismatch means the two ALTS endpoints cannot agree on a common gRPC RPC protocol version.","triggerScenarios":"A gRPC-Go ALTS client (NewClientCreds) completes the ALTS cryptographic handshake to an ALTS server, but the server's negotiated max/min RPC versions fall entirely outside [2.1, 2.1]. This path is reached only on GCP (vmOnGCP==true), after the handshaker service returns a result with PeerRPCVersions.","commonSituations":"Connecting from a much newer or older grpc-go build (whose hardcoded min/max RPC versions differ from 2.1) to a server running a different gRPC version, or to a handshaker service that reports unexpected versions. Can also appear when a test/staging environment runs a pre-release or custom-built gRPC.","solutions":["Align the gRPC version on the client and server so both advertise compatible ALTS RPC protocol versions (currently 2.1).","Upgrade (or downgrade) the grpc-go dependency on both ends to a matching release tag.","If you control both endpoints, verify the RpcProtocolVersions returned by the handshaker service and file an issue if they diverge unexpectedly."],"exampleFix":"// before: client on grpc-go v1.70, server on a build advertising RPC version 3.0\ncreds := alts.NewClientCreds(alts.DefaultClientOptions())\nconn, _ := grpc.Dial(addr, grpc.WithTransportCredentials(creds)) // version mismatch error\n\n// after: pin both client and server to the same grpc-go release\ngo get google.golang.org/grpc@v1.70.0 // on both sides","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Wrap the dial and surface version-mismatch as a typed error the app can handle.\nfunc dialAlTS(addr string, creds credentials.TransportCredentials) (*grpc.ClientConn, error) {\n    conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(creds))\n    if err != nil {\n        if strings.Contains(err.Error(), \"RPC versions are not compatible\") {\n            return nil, fmt.Errorf(\"ALTS version mismatch with %s: upgrade grpc-go on both ends: %w\", addr, err)\n        }\n        return nil, err\n    }\n    return conn, nil\n}","preventionTips":["Pin the same grpc-go version on ALTS clients and servers.","During rolling upgrades, verify ALTS RPC version ranges overlap before shifting traffic.","Log the full error (including local/peer versions) to quickly identify the mismatched side."],"tags":["grpc","alts","version-mismatch","gcp","handshake"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}