grpc/grpc-go · error
%v
Error message
%v
What it means
Returned inside doHandshake when the ALTS handshaker service's response carries a non-nil Status with a code other than OK (codes.OK==0). The error message is simply the Status.Details string from the handshaker service, surfacing whatever reason the GCP handshaker service gave for failing the handshake.
Solutions
- Read the wrapped Details string for the handshaker service's explanation and act on it (e.g. identity/account mismatch).
- For client handshakes, verify TargetServiceAccounts in ClientOptions match the server's service accounts.
- Check the bound access token (BoundAccessToken) is valid and not expired.
- Confirm both peers are on GCP and permitted to use ALTS; consult GCP IAM/ALTS policy.
- Retry if the Details suggest a transient handshaker-service issue.
Defensive patterns
Strategy: try-catch
Try / catch
// The handshaker service's Status.Details is opaque; log it for diagnosis.
if err != nil {
log.Printf("ALTS handshake rejected by handshaker service: %v", err)
// Distinguish identity/account issues (non-retryable) from transient ones.
if strings.Contains(err.Error(), "identity") || strings.Contains(err.Error(), "account") {
return err // fix config, do not blindly retry
}
// otherwise allow a bounded retry
} Prevention
- Verify TargetServiceAccounts (client) match the server's service accounts.
- Ensure BoundAccessToken is valid and unexpired when used.
- Check GCP IAM/ALTS policy permits both peers.
- Log Status.Details to classify rejection reasons.
When it happens
Trigger: The DoHandshake RPC stream is open and a response was received, but resp.Status.Code != 0. Reached for both client and server handshakes during doHandshake -> accessHandshakerService. The actual reason is opaque (just the Details string), so the cause lives inside the metadata-server handshaker.
Common situations: The peer's target service account does not match any identity the handshaker service expects (TargetServiceAccounts mismatch on the client); the client identity is not allowed; access token rejection; the peer closed/aborted the handshake; resource/quota limits inside the handshaker service.
Related errors
- failed to establish stream to ALTS handshaker service
- failed to receive ALTS handshaker response
- failed to send ALTS handshaker request
- client-side RPC versions is not compatible with this…
- server-side RPC versions are not compatible with this…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/1b4d775388ed0064.
Report an issue: GitHub.
Appendix: source
Thrown at credentials/alts/internal/handshaker/handshaker.go:271
}
conn, result, err := h.doHandshake(req)
if err != nil {
return nil, nil, err
}
authInfo := authinfo.New(result)
return conn, authInfo, nil
}
func (h *altsHandshaker) doHandshake(req *altspb.HandshakerReq) (net.Conn, *altspb.HandshakerResult, error) {
resp, err := h.accessHandshakerService(req)
if err != nil {
return nil, nil, err
}
// Check of the returned status is an error.
if resp.GetStatus() != nil {
if got, want := resp.GetStatus().Code, uint32(codes.OK); got != want {
return nil, nil, fmt.Errorf("%v", resp.GetStatus().Details)
}
}
var extra []byte
if req.GetServerStart() != nil {
if resp.GetBytesConsumed() > uint32(len(req.GetServerStart().GetInBytes())) {
return nil, nil, errOutOfBound
}
extra = req.GetServerStart().GetInBytes()[resp.GetBytesConsumed():]
}
result, extra, err := h.processUntilDone(resp, extra)
if err != nil {
return nil, nil, err
}
// The handshaker returns a 128 bytes key. It should be truncated based
// on the returned record protocol.
keyLen, ok := keyLength[result.RecordProtocol]
if !ok {View on GitHub (pinned to 0c51461d27)