TooTallNate/Java-WebSocket · error · IllegalArgumentException

parameter must not be null

Error message

parameter must not be null

What it means

The SSLSocketChannel constructor requires a non-null SocketChannel, SSLEngine, and ExecutorService. Note the source contains a real bug: it checks `executor == inputExecutor` (field, still null at that point) instead of `inputExecutor == null`, so the intended null-check for the executor is broken and a null executor is only caught indirectly later. If any checked argument is null, IllegalArgumentException('parameter must not be null') is thrown at construction time.

Solutions

  1. Check each argument for null before constructing SSLSocketChannel and fail with a clear message
  2. Fix or verify the library version: newer versions check inputExecutor == null; upgrade if you rely on executor validation
  3. Ensure SSLEngine creation (SSLContext) and socketChannel acquisition succeeded before wiring the channel

Example fix

// before
new SSLSocketChannel(channel, null, executor, key); // throws
// after
if (channel == null || sslEngine == null || executor == null) {
  throw new IllegalArgumentException("channel, sslEngine and executor are required");
}
new SSLSocketChannel(channel, sslEngine, executor, key);
Defensive patterns

Strategy: type-guard

Validate before calling

java.util.Objects.requireNonNull(channel, "channel");
java.util.Objects.requireNonNull(sslEngine, "sslEngine");
java.util.Objects.requireNonNull(executor, "executor");

Type guard

boolean argsValid = (channel != null && sslEngine != null && executor != null);

Try / catch

try { new SSLSocketChannel(ch, engine, exec, key); } catch (IllegalArgumentException e) { log.error("SSL channel wiring failed: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Passing null for inputSocketChannel or inputEngine to new SSLSocketChannel(...). A null inputExecutor is NOT reliably rejected due to the `executor == inputExecutor` bug (it throws only if the field is non-null, which it never is in the constructor).

Common situations: Building an SSL-enabled WebSocketServer where the SSLEngine failed to create (bad keystore) or the socket channel was null after an accept failure, and the null was passed straight through.

Related errors


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

Appendix: source

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

   * to this value should normally cause no capacity problems. However, some implementations violate
   * the specification and generate large records up to 32 KB. If the {@link
   * SSLEngine#unwrap(ByteBuffer, ByteBuffer)} detects large inbound packets, the buffer sizes
   * returned by SSLSession will be updated dynamically, so the this peer should check for overflow
   * conditions and enlarge the buffer using the session's (updated) buffer size.
   */
  private ByteBuffer peerNetData;

  /**
   * Will be used to execute tasks that may emerge during handshake in parallel with the server's
   * main thread.
   */
  private ExecutorService executor;


  public SSLSocketChannel(SocketChannel inputSocketChannel, SSLEngine inputEngine,
      ExecutorService inputExecutor, SelectionKey key) throws IOException {
    if (inputSocketChannel == null || inputEngine == null || executor == inputExecutor) {
      throw new IllegalArgumentException("parameter must not be null");
    }

    this.socketChannel = inputSocketChannel;
    this.engine = inputEngine;
    this.executor = inputExecutor;
    myNetData = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());
    peerNetData = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());
    this.engine.beginHandshake();
    if (doHandshake()) {
      if (key != null) {
        key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
      }
    } else {
      try {
        socketChannel.close();
      } catch (IOException e) {
        log.error("Exception during the closing of the channel", e);
      }

View on GitHub (pinned to afeacbf8c0)