{"record":{"id":"7c699739726d3fe9","repo":"grpc/grpc-go","slug":"failed-to-send-alts-handshaker-request-w","errorCode":null,"errorMessage":"failed to send ALTS handshaker request: %w","messagePattern":"failed to send ALTS handshaker request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/alts/internal/handshaker/handshaker.go","lineNumber":305,"sourceCode":"\t// on the returned record protocol.\n\tkeyLen, ok := keyLength[result.RecordProtocol]\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"unknown resulted record protocol %v\", result.RecordProtocol)\n\t}\n\tmaxFrameSize := int(envconfig.ALTSMaxFrameSize)\n\tif peerMax := int(result.GetMaxFrameSize()); peerMax > 0 {\n\t\tmaxFrameSize = min(peerMax, maxFrameSize)\n\t}\n\tsc, err := conn.NewConnWithMaxFrameSize(h.conn, h.side, result.GetRecordProtocol(), result.KeyData[:keyLen], extra, maxFrameSize)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn sc, result, nil\n}\n\nfunc (h *altsHandshaker) accessHandshakerService(req *altspb.HandshakerReq) (*altspb.HandshakerResp, error) {\n\tif err := h.stream.Send(req); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to send ALTS handshaker request: %w\", err)\n\t}\n\tresp, err := h.stream.Recv()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to receive ALTS handshaker response: %w\", err)\n\t}\n\treturn resp, nil\n}\n\n// processUntilDone processes the handshake until the handshaker service returns\n// the results. Handshaker service takes care of frame parsing, so we read\n// whatever received from the network and send it to the handshaker service.\nfunc (h *altsHandshaker) processUntilDone(resp *altspb.HandshakerResp, extra []byte) (*altspb.HandshakerResult, []byte, error) {\n\tvar lastWriteTime time.Time\n\tbuf := make([]byte, frameLimit)\n\tfor {\n\t\tif len(resp.OutFrames) > 0 {\n\t\t\tlastWriteTime = time.Now()\n\t\t\tif _, err := h.conn.Write(resp.OutFrames); err != nil {","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/alts/internal/handshaker/handshaker.go#L287-L323","documentation":"Returned by accessHandshakerService when sending a HandshakerReq on the open DoHandshake stream fails (h.stream.Send returns an error). The underlying error is wrapped with %w so it can be unwrapped/errors.Is-checked. This is a mid-handshake transport failure on the control stream to the GCP handshaker service.","triggerScenarios":"After the DoHandshake stream is established (so not 191/192), a subsequent Send of a ClientStart/ServerStart/Next request fails. Reached on every accessHandshakerService call during doHandshake and processUntilDone loops.","commonSituations":"The metadata-server handshaker service closed/reset the stream mid-handshake; network interruption to metadata.google.internal.:8080; context cancellation/deadline (e.g. the 30s server timeout) cancelling the stream; the peer aborted; gRPC keepalive closing an idle handshaker stream.","solutions":["Retry the ALTS connection — these are typically transient stream breaks.","Ensure the context used for the handshake has an adequate deadline (server-side default is 30s).","Check network connectivity and handshaker-service health; verify GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES is not exhausted.","Inspect the wrapped error (errors.Unwrap / errors.Is io.EOF, context.DeadlineExceeded) to distinguish cancellation from a genuine transport error."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Stream Send failures during handshake are transient; retry the ALTS connection.\nif err != nil {\n    if errors.Is(err, io.EOF) || errors.Is(err, context.DeadlineExceeded) {\n        // transient — retry with backoff\n    }\n    if strings.Contains(err.Error(), \"failed to send ALTS handshaker request\") {\n        return fmt.Errorf(\"ALTS handshaker stream broken: %w\", err)\n    }\n}","preventionTips":["Use a context with sufficient deadline for ALTS handshakes (server default 30s).","Monitor handshaker stream Send failures and alert on spikes.","Ensure network connectivity to the metadata server is stable."],"tags":["grpc","alts","gcp","handshaker-service","network","transient","stream"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}