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

  1. Verify the ALTS handshaker service address is reachable (network/firewall/DNS) and the service is running
  2. Retry the handshake — transient disconnects typically succeed on retry
  3. Check handshaker service logs for why it closed the stream before responding
  4. 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

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

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/f54663f9d9cee795. Report an issue: GitHub.