{"record":{"id":"1a072e1cf4ad75c5","repo":"grpc/grpc-go","slug":"failed-to-establish-stream-to-alts-handshaker-serv","errorCode":null,"errorMessage":"failed to establish stream to ALTS handshaker service: %v","messagePattern":"failed to establish stream to ALTS handshaker service: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/alts/internal/handshaker/handshaker.go","lineNumber":173,"sourceCode":"\n// ClientHandshake starts and completes a client ALTS handshake for GCP. Once\n// done, ClientHandshake returns a secure connection.\nfunc (h *altsHandshaker) ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) {\n\tif err := clientHandshakes.Acquire(ctx, 1); err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer clientHandshakes.Release(1)\n\n\tif h.side != core.ClientSide {\n\t\treturn nil, nil, errors.New(\"only handshakers created using NewClientHandshaker can perform a client handshaker\")\n\t}\n\n\t// TODO(matthewstevenson88): Change unit tests to use public APIs so\n\t// that h.stream can unconditionally be set based on h.clientConn.\n\tif h.stream == nil {\n\t\tstream, err := altsgrpc.NewHandshakerServiceClient(h.clientConn).DoHandshake(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to establish stream to ALTS handshaker service: %v\", err)\n\t\t}\n\t\th.stream = stream\n\t}\n\n\t// Create target identities from service account list.\n\ttargetIdentities := make([]*altspb.Identity, 0, len(h.clientOpts.TargetServiceAccounts))\n\tfor _, account := range h.clientOpts.TargetServiceAccounts {\n\t\ttargetIdentities = append(targetIdentities, &altspb.Identity{\n\t\t\tIdentityOneof: &altspb.Identity_ServiceAccount{\n\t\t\t\tServiceAccount: account,\n\t\t\t},\n\t\t})\n\t}\n\treq := &altspb.HandshakerReq{\n\t\tReqOneof: &altspb.HandshakerReq_ClientStart{\n\t\t\tClientStart: &altspb.StartClientHandshakeReq{\n\t\t\t\tHandshakeSecurityProtocol: hsProtocol,\n\t\t\t\tApplicationProtocols:      appProtocols,","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/alts/internal/handshaker/handshaker.go#L155-L191","documentation":"In altsHandshaker.ClientHandshake (handshaker.go:170-174), the client opens a bidirectional streaming RPC (DoHandshake) to the ALTS handshaker service running on GCP via h.clientConn. If that gRPC stream cannot be established, the error is wrapped as \"failed to establish stream to ALTS handshaker service\". The clientConn is the one returned by service.Dial(hsAddress).","triggerScenarios":"Performing an ALTS client handshake when the connection to the local ALTS handshaker service (the GCP ALTS-MDB endpoint) cannot be opened — network error, service unavailable, deadline, or auth failure talking to the handshaker service.","commonSituations":"Running ALTS outside GCP (where the handshaker service is absent); GCP metadata server / ALTS daemon not reachable; firewall blocking the handshaker service port; transient GCP control-plane issue; the hsAddress is misconfigured.","solutions":["Confirm the workload is actually on GCP and the ALTS handshaker service is reachable (ErrUntrustedPlatform is a related earlier guard).","Check the inner %v for the stream RPC error (UNAVAILABLE, DEADLINE_EXCEEDED, PERMISSION_DENIED) and address it.","If not on GCP, switch to TLS credentials instead of ALTS."],"exampleFix":"// before\ncreds, _ := alts.NewClientCreds(...)\nconn, _ := grpc.NewClient(target, grpc.WithTransportCredentials(creds))  // off GCP\n// after (off GCP)\ncreds := credentials.NewTLS(&tls.Config{ServerName: target})\nconn, _ := grpc.NewClient(target, grpc.WithTransportCredentials(creds))","handlingStrategy":"try-catch","validationCode":"// Confirm you are on GCP before attempting ALTS; otherwise use TLS.\nfunc onGCP() bool { _, err := metadata.Get(\"instance/zone\"); return err == nil }","typeGuard":null,"tryCatchPattern":"secConn, authInfo, err := chs.ClientHandshake(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to establish stream to ALTS handshaker service\") {\n        log.Printf(\"ALTS handshaker service unreachable: %v; falling back to TLS\", err)\n        // fall back to a TLS credentials handshake instead\n    }\n    return nil, nil, err\n}","preventionTips":["Gate ALTS usage behind a GCP-platform check; use TLS elsewhere.","Ensure the ALTS handshaker service address/port is reachable (firewall, metadata).","Retry with backoff on transient UNAVAILABLE from the handshaker service."],"tags":["go","grpc","alts","security","network"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}