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

  1. Read the wrapped Details string for the handshaker service's explanation and act on it (e.g. identity/account mismatch).
  2. For client handshakes, verify TargetServiceAccounts in ClientOptions match the server's service accounts.
  3. Check the bound access token (BoundAccessToken) is valid and not expired.
  4. Confirm both peers are on GCP and permitted to use ALTS; consult GCP IAM/ALTS policy.
  5. 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

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


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)