TooTallNate/Java-WebSocket · error · InvalidDataException

1002

1002

Error message

A close frame must have a closecode if it has a reason

What it means

CloseFrame.isValid enforces that a close frame carrying a reason string must have an actual close code. Close code 0 (NOCODE) is reserved for internal representation and is not valid on the wire; sending a reason with NOCODE is contradictory, so InvalidDataException(1002 PROTOCOL_ERROR) is thrown.

Solutions

  1. Provide a valid close code (1000, 1001, 1011, or 3000-4999) whenever a reason string is included.
  2. If no code is known, send NOCODE with an empty reason, or let the library generate the frame.
  3. Clamp/validate application close codes to the allowed ranges before calling close(code, reason).

Example fix

// before
webSocket.close(0, "shutting down"); // invalid: NOCODE with reason

// after
webSocket.close(1000, "shutting down");
Defensive patterns

Strategy: validation

Validate before calling

// guard before calling close
if ((code == 0 || code == CloseFrame.NOCODE) && reason != null && !reason.isEmpty()) {
    throw new IllegalArgumentException("a close code is required when a reason is provided");
}

Try / catch

try {
    webSocket.close(code, reason);
} catch (InvalidDataException e) {
    logger.warn("rejected close frame: {}", e.getMessage());
    webSocket.close(1000); // fall back to a valid frame
}

Prevention

When it happens

Trigger: Building a CloseFrame whose code is CloseFrame.NOCODE (0) while the reason string is non-empty, e.g. calling close with code 0 plus a message, then isValid() rejects it before sending.

Common situations: Passing 0 as the close code by default/accident along with a reason; unmapped error paths that forward raw codes; tests constructing close frames manually.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/org/java_websocket/framing/CloseFrame.java:232

   * @return the message in this frame
   */
  public String getMessage() {
    return reason;
  }

  @Override
  public String toString() {
    return super.toString() + "code: " + code;
  }

  @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) {

View on GitHub (pinned to afeacbf8c0)