grpc/grpc-java · error · IOException
No handshaker response received
Error message
No handshaker response received
What it means
AltsHandshakerStub.send() blocks on a response from the handshaker service. If the take() returns an empty Optional (stream closed / EOF) and no exception message was recorded, the handshake ended without any response, so send() throws IOException("No handshaker response received").
Source
Thrown at alts/src/main/java/io/grpc/alts/internal/AltsHandshakerStub.java:77
/** Send a handshaker request and return the handshaker response. */
public HandshakerResp send(HandshakerReq req) throws InterruptedException, IOException {
createWriterIfNull();
maybeThrowIoException();
if (!responseQueue.isEmpty()) {
throw new IOException("Received an unexpected response.");
}
writer.onNext(req);
Optional<HandshakerResp> result = responseQueue.take();
if (result.isPresent()) {
return result.get();
}
if (exceptionMessage.get() != null) {
throw new IOException(exceptionMessage.get().info, exceptionMessage.get().throwable);
} else {
throw new IOException("No handshaker response received");
}
}
/** Create a new writer if the writer is null. */
private void createWriterIfNull() {
if (writer == null) {
writer =
serviceStub.withDeadlineAfter(HANDSHAKE_RPC_DEADLINE_SECS, SECONDS).doHandshake(reader);
}
}
/** Throw exception if there is an outstanding exception. */
private void maybeThrowIoException() throws IOException {
if (exceptionMessage.get() != null) {
throw new IOException(exceptionMessage.get().info, exceptionMessage.get().throwable);
}
}
View on GitHub (pinned to 64daddc1f3)
Solutions
- Verify the ALTS handshaker service address is reachable (network/firewall/DNS) and the service is running
- Retry the handshake — transient disconnects typically succeed on retry
- Check handshaker service logs for why it closed the stream before responding
- Catch IOException from send() and rebuild the stub before retrying, since the stream is closed
Example fix
// before
HandshakerResp resp = stub.send(req); // IOException on abrupt stream close
// after
try {
HandshakerResp resp = stub.send(req);
} catch (IOException e) {
stub = createNewStub(handshakerAddr); // stream is dead; reconnect and retry
retryHandshake(stub);
} Defensive patterns
Strategy: retry
Validate before calling
// before handshake: check reachability
if (!isHandshakerServiceReachable(handshakerAddr)) {
throw new IOException("ALTS handshaker service unreachable: " + handshakerAddr);
} Type guard
null
Try / catch
try {
HandshakerResp resp = stub.send(req);
} catch (IOException e) {
stub = recreateStub();
retryWithBackoff();
} Prevention
- Verify handshaker service address/firewall/DNS before handshaking
- Monitor handshaker service health
- Always recreate the stub after a closed stream
When it happens
Trigger: The handshaker stream closes (onClose/onError) before delivering a HandshakerResp — e.g. connection to the handshaker service dropped immediately, service crashed, or stream cancelled before any response arrived.
Common situations: Handshaker service unreachable and the connection torn down before a response; network interruption mid-handshake; handshaker service rejecting the request and closing the stream without a status response.
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.
- Handshaker service error: ${status.getDetails()}
- Received an unexpected response.
- TsiHandshakeHandler encountered exception
- No ALTS context information found
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/f54663f9d9cee795.
Report an issue: GitHub.