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
- Allocate app/net buffers via engine.getSession().getApplicationBufferSize()/getPacketBufferSize() (or the library's enlargeBuffer helpers)
- Catch IllegalStateException, resize peerNetData/peerAppData and retry the unwrap
- 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
- Size read buffers from engine.getSession() capacities, with room to grow
- Keep the library and JDK updated so all SSLEngineResult.Status values are handled
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.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- parameter must not be null
- Buffer underflow occurred after a wrap. I don't think we…
- parameter must not be null
- can only be started once.
- buffer size < 0
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)