TooTallNate/Java-WebSocket · error · EOFException
Connection is closed
Error message
Connection is closed
What it means
SSLSocketChannel2.write() throws EOFException when, after attempting to wrap and write data, the SSLEngine reports Status.CLOSED — i.e. the TLS session has already been closed (close_notify received or engine closed) and no more application data can be sent. The library converts this TLS state into EOFException so callers stop writing.
Solutions
- Check websocket.isOpen() (or ReadyState == OPEN) before sending.
- Route all sends through a single thread or synchronize access so writes cannot race with close.
- Catch WebsocketNotConnectedException/EOFException around send() and drop or requeue the message.
- Reconnect via WebSocketClient.reconnect() if the message must be delivered after an unexpected close.
Example fix
// before
conn.send(payload);
// after
if (conn.isOpen()) {
conn.send(payload);
} else {
queueForResend(payload);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!conn.isOpen()) { /* skip or queue send */ } Type guard
boolean canSend = conn != null && conn.isOpen() && conn.getReadyState().equals(ReadyState.OPEN);
Try / catch
try { conn.send(data); } catch (WebsocketNotConnectedException | EOFException e) { queueForResend(data); } Prevention
- Always check isOpen() before send
- Serialize all sends through one thread/executor
- Don't hold references to sockets after onClose fires
When it happens
Trigger: Calling write()/send() on a WebSocket whose SSL engine has closed: after the peer sent close_notify, after closeConnection was initiated, or a concurrent write raced with the close handshake.
Common situations: Sending a message from another thread while the connection is closing; server closed the connection but the client queue still has pending frames; missed the onClose callback before issuing a send.
Related errors
AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09).
Data as JSON: /api/errors/c3994cd5a9ed7d24.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/java_websocket/SSLSocketChannel2.java:285
inCrypt.rewind();
inCrypt.flip();
outCrypt.rewind();
outCrypt.flip();
bufferallocations++;
}
public int write(ByteBuffer src) throws IOException {
if (!isHandShakeComplete()) {
processHandshake(false);
return 0;
}
// assert(bufferallocations > 1); // see #190
// if(bufferallocations <= 1) {
// createBuffers(sslEngine.getSession());
// }
int num = socketChannel.write(wrap(src));
if (writeEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) {
throw new EOFException("Connection is closed");
}
return num;
}
/**
* Blocks when in blocking mode until at least one byte has been decoded.<br> When not in blocking
* mode 0 may be returned.
*
* @return the number of bytes read.
**/
public int read(ByteBuffer dst) throws IOException {
tryRestoreCryptedData();
while (true) {
if (!dst.hasRemaining()) {
return 0;
}
if (!isHandShakeComplete()) {View on GitHub (pinned to afeacbf8c0)