TooTallNate/Java-WebSocket · error · InvalidFrameException
closecode must not be sent over the wire
Error message
closecode must not be sent over the wire: {code} What it means
This is the final wire-safety check in CloseFrame.isValid: certain codes must never appear in a close frame sent over the network — ABNORMAL_CLOSE (1006), TLS_ERROR (1015), NOCODE (0), codes outside 1000-4999, and the reserved 1004. Violating this throws InvalidFrameException with the offending code embedded in the message.
Solutions
- Never send 1006/1015/0/1004 — these are generated internally by the library to signal local conditions.
- Map desired meanings to allowed codes: 1000 normal, 1001 going away, 1011 server error, 4000-4999 app-defined.
- Add a pre-send guard in your code that rejects codes in the forbidden set.
- Inspect the message's trailing number to identify which illegal code was used.
Example fix
// before webSocket.close(1006, "connection dropped"); // 1006 never goes on the wire // after webSocket.close(1001, "connection dropped");
Defensive patterns
Strategy: validation
Validate before calling
static final Set<Integer> FORBIDDEN = Set.of(1004, 1005, 1006, 1015, 0);
static boolean canSendCode(int code) {
return !FORBIDDEN.contains(code) && code >= 1000 && code <= 4999;
} Try / catch
try {
webSocket.close(code, reason);
} catch (InvalidFrameException e) {
logger.error("illegal close code attempted: {}", e.getMessage());
webSocket.close(1001); // safe substitute
} Prevention
- Never echo 1006/1015 back to peers — they are internal-only signals
- Map internal error numbers to legal close codes explicitly
- Unit-test your close-code mapping table
When it happens
Trigger: Constructing or sending a CloseFrame whose code is 1006, 1015, 0, 1004, < 1000, or > 4999; isValid() runs during frame construction/send (also invoked from WebSocket.close).
Common situations: Trying to echo back a 1006 abnormal closure received from the peer (1006 is never a wire code); forwarding I/O error codes like -1 or 0; using codes above 4999 for app semantics.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09).
Data as JSON: /api/errors/508fb5c7b6c37fd1.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/java_websocket/framing/CloseFrame.java:241
}
@Override
public void isValid() throws InvalidDataException {
super.isValid();
if (code == CloseFrame.NO_UTF8 && reason.isEmpty()) {
throw new InvalidDataException(CloseFrame.NO_UTF8, "Received text is no valid utf8 string!");
}
if (code == CloseFrame.NOCODE && 0 < reason.length()) {
throw new InvalidDataException(PROTOCOL_ERROR,
"A close frame must have a closecode if it has a reason");
}
//Intentional check for code != CloseFrame.TLS_ERROR just to make sure even if the code earlier changes
if ((code > CloseFrame.TLS_ERROR && code < 3000)) {
throw new InvalidDataException(PROTOCOL_ERROR, "Trying to send an illegal close code!");
}
if (code == CloseFrame.ABNORMAL_CLOSE || code == CloseFrame.TLS_ERROR
|| code == CloseFrame.NOCODE || code > 4999 || code < 1000 || code == 1004) {
throw new InvalidFrameException("closecode must not be sent over the wire: " + code);
}
}
@Override
public void setPayload(ByteBuffer payload) {
code = CloseFrame.NOCODE;
reason = "";
payload.mark();
if (payload.remaining() == 0) {
code = CloseFrame.NORMAL;
} else if (payload.remaining() == 1) {
code = CloseFrame.PROTOCOL_ERROR;
} else {
if (payload.remaining() >= 2) {
ByteBuffer bb = ByteBuffer.allocate(4);
bb.position(2);
bb.putShort(payload.getShort());
bb.position(0);View on GitHub (pinned to afeacbf8c0)