{"record":{"id":"4d7f7a5d3b528f10","repo":"grpc/grpc-java","slug":"tsihandshakehandler-encountered-exception","errorCode":null,"errorMessage":"TsiHandshakeHandler encountered exception","messagePattern":"TsiHandshakeHandler encountered exception","errorType":"exception","errorClass":"GeneralSecurityException","httpStatus":null,"severity":"error","filePath":"alts/src/main/java/io/grpc/alts/internal/TsiHandshakeHandler.java","lineNumber":221,"sourceCode":"    ctx.fireUserEventTriggered(localPne);\n  }\n\n  /** Sends as many bytes as are available from the handshaker to the remote peer. */\n  @SuppressWarnings(\"FutureReturnValueIgnored\") // for addListener\n  private void sendHandshake(ChannelHandlerContext ctx) throws GeneralSecurityException {\n    while (true) {\n      boolean written = false;\n      ByteBuf buf = ctx.alloc().buffer(HANDSHAKE_FRAME_SIZE).retain(); // refcnt = 2\n      try {\n        handshaker.getBytesToSendToPeer(buf);\n        if (buf.isReadable()) {\n          ctx.writeAndFlush(buf).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);\n          written = true;\n        } else {\n          break;\n        }\n      } catch (GeneralSecurityException e) {\n        throw new GeneralSecurityException(\"TsiHandshakeHandler encountered exception\", e);\n      } finally {\n        buf.release(written ? 1 : 2);\n      }\n    }\n  }\n\n  @Override\n  protected void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {\n    if (semaphoreAcquired) {\n      semaphoreRelease();\n      semaphoreAcquired = false;\n    }\n    handshaker.close();\n  }\n\n  private ChannelFuture semaphoreAcquire(ChannelHandlerContext ctx) {\n    if (semaphore == null) {\n      return ctx.newSucceededFuture();","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/alts/src/main/java/io/grpc/alts/internal/TsiHandshakeHandler.java#L203-L239","documentation":"TsiHandshakeHandler.sendHandshake() flushes queued TSI handshake frames through the TSI transport; if the underlying TsiTransport's write raises GeneralSecurityException, the handler wraps it in a new GeneralSecurityException labeled \"TsiHandshakeHandler encountered exception\", preserving the cause. This marks the ALTS/TSI handshake as failed at the Netty pipeline level.","triggerScenarios":"A GeneralSecurityException thrown while writing handshake frames during decode(), userEventTriggered(), or a write-future callback (operationComplete) — typically encryption/counter failures or corrupt handshake data while sending.","commonSituations":"Corrupted handshake bytes on the wire, a failing ALTS crypter (e.g. counter issues), or handshake data written after the peer already aborted the handshake.","solutions":["Inspect the wrapped cause (getCause()) to find the real failure (crypter vs framing vs transport)","Fail and close the channel, then re-establish the connection with a fresh handshake","Verify both peers use compatible ALTS/TSI versions and the byte stream isn't corrupted by intermediate proxies","Enable TsiHandshakeHandler debug logging to identify which frame write failed"],"exampleFix":"// pipeline side: handle the failure and close\npipeline().addLast(new TsiHandshakeHandler(peer)) {\n  @Override\n  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {\n    cause.printStackTrace(); // includes the wrapped GeneralSecurityException\n    ctx.close(); // handshake is unrecoverable; reconnect\n  }\n};","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  handshakeHandler.sendHandshake(ctx);\n} catch (GeneralSecurityException e) {\n  log.severe(\"TSI handshake failed: \" + e.getCause());\n  ctx.close(); // close channel and reconnect with a new handshake\n}","preventionTips":["Always inspect getCause() to find the root security failure","Implement exceptionCaught in the pipeline to close the channel on handshake failure","Keep ALTS/TSI versions consistent across peers"],"tags":["grpc","alts","tsi","handshake","netty"],"backgroundTag":"handshake-failed","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}