grpc/grpc-java · error · GeneralSecurityException
Handshaker service error: ${status.getDetails()}
Error message
Handshaker service error: ${status.getDetails()} What it means
AltsHandshakerClient.handleResponse() checks the status code embedded in each HandshakerResp returned by the ALTS handshaker service. Any non-OK status (e.g. INTERNAL, INVALID_ARGUMENT, UNAUTHENTICATED) aborts the handshake: the client logs the details, closes the stream, and throws GeneralSecurityException carrying the service's details string.
Source
Thrown at alts/src/main/java/io/grpc/alts/internal/AltsHandshakerClient.java:162
byte[] key = new byte[KEY_LENGTH];
result.getKeyData().substring(0, KEY_LENGTH).copyTo(key, 0);
return key;
}
/**
* Parses a handshake response, setting the status, result, and closing the handshaker, as needed.
*/
private void handleResponse(HandshakerResp resp) throws GeneralSecurityException {
status = resp.getStatus();
if (resp.hasResult()) {
result = resp.getResult();
close();
}
if (status.getCode() != Status.Code.OK.value()) {
String error = "Handshaker service error: " + status.getDetails();
logger.log(ChannelLogLevel.DEBUG, error);
close();
throw new GeneralSecurityException(error);
}
}
/**
* Starts a client handshake. A GeneralSecurityException is thrown if the handshaker service is
* interrupted or fails. Note that isFinished() must be false before this function is called.
*
* @return the frame to give to the peer.
* @throws GeneralSecurityException or IllegalStateException
*/
public ByteBuffer startClientHandshake() throws GeneralSecurityException {
Preconditions.checkState(!isFinished(), "Handshake has already finished.");
HandshakerReq.Builder req = HandshakerReq.newBuilder();
setStartClientFields(req);
HandshakerResp resp;
try {
logger.log(ChannelLogLevel.DEBUG, "Send ALTS handshake request to upstream");
resp = handshakerStub.send(req.build());View on GitHub (pinned to 64daddc1f3)
Solutions
- Read status.getDetails() in the exception message — it names the service-side reason; fix the underlying identity/protocol problem
- Verify both peers run in an environment supporting ALTS (e.g. correct GCP service accounts and Compute Engine metadata)
- Confirm the handshaker service address/port is correct and the service is healthy
- Retry the connection; transient handshaker service errors often resolve on a new handshake
Example fix
// before
AltsChannelBuilder.forTarget(target).handshakerAddress(badAddr).build();
// after
AltsChannelBuilder.forTarget(target)
.handshakerAddress("metadata.google.internal:8080")
.build(); // and retry on GeneralSecurityException Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
try {
client.startClientHandshake(next);
} catch (GeneralSecurityException e) {
logger.warn("ALTS handshake failed: " + e.getMessage()); // includes status details
scheduleReconnectWithBackoff();
} Prevention
- Log and inspect status details — they identify IAM/identity or protocol problems
- Validate GCP service accounts and ALTS environment before deploying
- Add exponential backoff retry for transient handshaker service errors
When it happens
Trigger: The remote ALTS handshaker service returns a non-OK status in a response during startClientHandshake, startServerHandshake, or next() — e.g. peer identity rejected, unsupported handshake protocol, or service-side failure.
Common situations: Mismatched peer service accounts / IAM roles for ALTS on GCP, unsupported ALTS protocol negotiated, handshaker service outage, or wrong handshaker service address configured.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Could not get enough key data from the handshake.
- Received an unexpected response.
- No handshaker response received
- TsiHandshakeHandler encountered exception
- No ALTS context information found
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/08429b45c30792a0.
Report an issue: GitHub.