TooTallNate/Java-WebSocket · error · SSLException

Buffer underflow occurred after a wrap. I don't think we…

Error message

Buffer underflow occurred after a wrap. I don't think we should ever get here.

What it means

During SSLSocketChannel.write(), engine.wrap() returned BUFFER_UNDERFLOW. BUFFER_UNDERFLOW from wrap() is contradictory — wrap consumes application data and produces network data, so it should never report 'not enough inbound data'. The library treats it as an unrecoverable TLS-layer anomaly and throws SSLException.

Solutions

  1. Verify you are not swapping arguments: wrap consumes myAppData and writes to myNetData
  2. Catch SSLException, close the connection and reconnect/rehandshake
  3. Upgrade the JDK/library — this usually indicates an engine-level bug

Example fix

// before
channel.writeAndHandshake(data); // throws SSLException on underflow
// after
try {
  channel.writeAndHandshake(data);
} catch (SSLException e) {
  channel.closeConnection();
  reconnect();
}
Defensive patterns

Strategy: try-catch

Try / catch

try { channel.write(data); } catch (SSLException e) { log.error("TLS write failed: {}", e.getMessage()); channel.closeConnection(); scheduleReconnect(); }

Prevention

When it happens

Trigger: engine.wrap(myAppData, myNetData) inside write() returns SSLEngineResult.Status.BUFFER_UNDERFLOW — essentially only possible with a corrupted/misconfigured SSLEngine or wrong buffers handed to wrap().

Common situations: Rare; seen with custom SSLEngine implementations, JDK TLS bugs, or code that accidentally swapped the app/net buffers passed to wrap().

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/38b075d41db3d973. Report an issue: GitHub.

Appendix: source

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

  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()) {
        case OK:
          myNetData.flip();
          while (myNetData.hasRemaining()) {
            num += socketChannel.write(myNetData);
          }
          break;
        case BUFFER_OVERFLOW:
          myNetData = enlargePacketBuffer(myNetData);
          break;
        case BUFFER_UNDERFLOW:
          throw new SSLException(
              "Buffer underflow occurred after a wrap. I don't think we should ever get here.");
        case CLOSED:
          closeConnection();
          return 0;
        default:
          throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
      }
    }
    return num;
  }

  /**
   * Implements the handshake protocol between two peers, required for the establishment of the
   * SSL/TLS connection. During the handshake, encryption configuration information - such as the
   * list of available cipher suites - will be exchanged and if the handshake is successful will
   * lead to an established SSL/TLS session.
   * <p>
   * <p/>

View on GitHub (pinned to afeacbf8c0)