TooTallNate/Java-WebSocket · error · IllegalStateException

Invalid SSL status:

Error message

Invalid SSL status: 

What it means

In SSLSocketChannel.read(), after unwrap() the SSLEngine result status can be OK, CLOSED, BUFFER_UNDERFLOW or BUFFER_OVERFLOW; only the first two are handled. Any other status (or an unexpected Status value) reaches the default branch and throws IllegalStateException('Invalid SSL status: ' + result.getStatus()).

Solutions

  1. Allocate app/net buffers via engine.getSession().getApplicationBufferSize()/getPacketBufferSize() (or the library's enlargeBuffer helpers)
  2. Catch IllegalStateException, resize peerNetData/peerAppData and retry the unwrap
  3. Upgrade the library to a version that handles all SSLEngineResult.Status values in read()

Example fix

// before
switch (result.getStatus()) { case OK: ...; case CLOSED: ...; default: throw ...; }
// after
if (result.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
  peerNetData = enlargeInboundBuffer(peerNetData); // then retry unwrap
}
if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
  peerAppData = enlargeApplicationBuffer(peerAppData); // then retry unwrap
}
Defensive patterns

Strategy: try-catch

Validate before calling

int pkt = engine.getSession().getPacketBufferSize();
int app = engine.getSession().getApplicationBufferSize();
// ensure peerNetData.capacity() >= pkt and peerAppData.capacity() >= app before reading

Try / catch

try { channel.read(dst); } catch (IllegalStateException e) { log.warn("Unexpected SSL status during read: {}", e.getMessage()); channel.closeConnection(); }

Prevention

When it happens

Trigger: unwrap() during read returns Status.BUFFER_OVERFLOW/BUFFER_UNDERFLOW or a non-standard status that the switch does not cover.

Common situations: Peer sends TLS records larger than the allocated peerNetData buffer (underflow path mishandled) or application buffers sized smaller than the negotiated session's application-buffer size.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09). Data as JSON: /api/errors/e1b92928397ce425. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/org/java_websocket/SSLSocketChannel.java:197

          log.error("SSLException during unwrap", e);
          throw e;
        }
        switch (result.getStatus()) {
          case OK:
            peerAppData.flip();
            return ByteBufferUtils.transferByteBuffer(peerAppData, dst);
          case BUFFER_UNDERFLOW:
            peerAppData.flip();
            return ByteBufferUtils.transferByteBuffer(peerAppData, dst);
          case BUFFER_OVERFLOW:
            peerAppData = enlargeApplicationBuffer(peerAppData);
            return read(dst);
          case CLOSED:
            closeConnection();
            dst.clear();
            return -1;
          default:
            throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
        }
      }
    } else if (bytesRead < 0) {
      handleEndOfStream();
    }
    ByteBufferUtils.transferByteBuffer(peerAppData, dst);
    return bytesRead;
  }

  @Override
  public synchronized int write(ByteBuffer output) throws IOException {
    int num = 0;
    while (output.hasRemaining()) {
      // The loop has a meaning for (outgoing) messages larger than 16KB.
      // Every wrap call will remove 16KB from the original message and send it to the remote peer.
      myNetData.clear();
      SSLEngineResult result = engine.wrap(output, myNetData);
      switch (result.getStatus()) {

View on GitHub (pinned to afeacbf8c0)